我正在创建一个派生自UserControl的自定义控件,我想将焦点设置到它上面。
这个自定义控件包含一个ComboBox控件和我在旁边绘制一些字符串。
ComboBox可以接收焦点,但我想能够将焦点设置到UserControl本身。 当我创建自定义控件并从父窗体调用CanFocus()时,我的OnPaint处理程序被设置为在具有焦点时略微不同,但它返回false。
是否有属性或其他内容需要设置?
我正在创建一个派生自UserControl的自定义控件,我想将焦点设置到它上面。
这个自定义控件包含一个ComboBox控件和我在旁边绘制一些字符串。
ComboBox可以接收焦点,但我想能够将焦点设置到UserControl本身。 当我创建自定义控件并从父窗体调用CanFocus()时,我的OnPaint处理程序被设置为在具有焦点时略微不同,但它返回false。
是否有属性或其他内容需要设置?
UserControl将会竭尽全力避免获取焦点。它有自动将焦点传递给子控件(如果存在)的代码,如果它确实获得了焦点。您至少需要覆盖WndProc()并拦截WM_SETFOCUS消息。可能还需要进行其他手术,如ControlStyles.Selectable和TabStop以及TabIndex属性。
您接下来面临的问题是,当UserControl确实具有焦点时,它不会对键盘消息做出有意义的响应。您需要检测UC背景上的点击以处理鼠标消息,并覆盖绘图,以使用户明确UC具有焦点(使用ControlPaint.DrawFocusRectangle)。如果这开始听起来不太吸引人,那是因为UC实际上是一个容器控件。
太长了,不适合作为评论,包含链接和代码……但这只是一条评论而已……
很多人抱怨一个UserControl没有触发“GotFocus()”事件。例如: UserControl and GotFocus() FYI:根据我的经验,“LostFocus()”会按预期触发。在过去的多个窗体项目中,我尝试在每个窗体上实现“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));
}
this.SetFocus();
,但这个方法并没有成功。在某些情况下,不希望焦点移动到UserControl的子元素。
在这种情况下,还需要将ControlStyles.ContainerControl设置为false。
Public Sub New()
InitializeComponent()
Me.SetStyle(ControlStyles.ContainerControl, False)
Me.SetStyle(ControlStyles.Selectable, True)
End Sub
来自 http://msdn.microsoft.com/en-us/library/system.windows.forms.control.canfocus.aspx
备注
为了使控件能够接收输入焦点,该控件必须分配一个句柄,并且对于该控件及其所有父控件,Visible 和 Enabled 属性都必须设置为 true,而且该控件必须是一个窗体或者该控件的最外层父控件必须是一个窗体。
确保您已满足这些先决条件。
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"。
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
var controls = this.Controls.Cast<Control>().ToList();
controls.ForEach(control => control.Enabled = false);
this.ActiveControl = null; //the UserControl will try to remember its ActiveControl
this.Focus();
controls.ForEach(control => control.Enabled = true);