我需要LinkLabel控件才能在单击时更改Focus。我设法使用this.SetStyle(ControlStyles.Selectable,false)作为按钮,如下所示:
class NoSelectButton : Button
{
public NoSelectButton()
{
// Button does not take focus when clicked
this.SetStyle(ControlStyles.Selectable, false);
}
}
但是,使用LinkLabels做同样的事情是行不通的。
class NoSelectLinkLabel : LinkLabel
{
public NoSelectLinkLabel()
{
// Link Label still gets focus when clicked
this.SetStyle(ControlStyles.Selectable, false);
}
}
有没有人能够了解我如何以我想要的方式工作?我对MSDN的印象是,在“GotFocus”,“LostFocus”和相关事件中对聚焦控件进行任何操作都是一个坏主意(来自“{警告”注释:http://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx)。
这是一个粗略的例子,显示了我所看到的行为:
using System.Windows.Forms;
namespace LinkLabelTests
{
public class Form1 : Form
{
NoSelectLinkLabel nsll;
NoSelectButton nsb;
TextBox tb;
public Form1()
{
this.SuspendLayout();
this.Width = 0;
this.Height = 0;
this.AutoSize = true;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
nsll = new NoSelectLinkLabel();
nsll.Text = "Link Label";
nsll.Top = this.Bottom;
this.Controls.Add(nsll);
nsb = new NoSelectButton();
nsb.Text = "Button";
nsb.Top = nsll.Bottom;
this.Controls.Add(nsb);
tb = new TextBox();
tb.Multiline = true;
tb.Text = "Select this text, then click the button or link";
tb.Width = 200;
tb.Height = 100;
tb.Top = nsb.Bottom;
this.Controls.Add(tb);
this.ResumeLayout();
}
}
}
答案 0 :(得分:0)
当你失去焦点时,你是否试图在TextBox中保持选择?如果是这样,请查看TextBoxBase.HideSelection。将其设置为false将允许您实现该目标。
http://msdn.microsoft.com/en-us/library/system.windows.forms.textboxbase.hideselection.aspx
答案 1 :(得分:0)
设置一些标志,以便您知道何时不希望TextBox失去焦点,然后在此处启用代码。此代码将忽略任何试图将焦点移开的控件。如您所述,某些控件会忽略ControlStyles.Selectable
class NoLoseFocusTextBox : TextBox
{
private const int WM_KILLFOCUS = 0x0008;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_KILLFOCUS) return;
base.WndProc(ref m);
}
}
更新
我决定将它变成一个更有用的控件。所有PInvoke
都是故意的。控件没有保持真正的焦点存在问题。这意味着你可以继续在键盘上打字,但我用PInvoke
和Focus()
修复了它。
class SnobbyFocusTextBox : TextBox
{
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private List<Control> mBlackList = new List<Control>();
public List<Control> BlackList
{
get
{
return mBlackList;
}
}
private const Int32 WM_KILLFOCUS = 0x0008;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_KILLFOCUS)
{
int newHandle = m.WParam.ToInt32();
foreach (Control c in mBlackList)
{
if (c.IsHandleCreated && c.Handle.ToInt32() == newHandle)
{
HandleRef reff1 = new HandleRef(this, Handle);
PostMessage(reff1, WM_SETFOCUS, IntPtr.Zero, c.Handle);
Focus();
}
}
}
base.WndProc(ref m);
}
}
像这样使用
nsb = new Button();
nsb.Text = "Button";
nsb.Top = nsll.Bottom;
this.Controls.Add(nsb);
tb = new SnobbyFocusTextBox();
tb.Multiline = true;
tb.Text = "Select this text, then click the button or link";
tb.Width = 200;
tb.Height = 100;
tb.Top = nsb.Bottom;
this.Controls.Add(tb);
tb.BlackList.Add(nsb);