How can I prevent a LinkLabel control from gaining focus when clicked?
I need the LinkLabel control to not change Focus when it is clicked. I managed to use this.SetStyle(ControlStyles.Selectable, false) for a button, like so:
class NoSelectButton : Button
{
public NoSelectButton()
{
// Button does not take focus when clicked
this.SetStyle(ControlStyles.Selectable, false);
}
}
But, doing this same thing with LinkLabels does not work.
class NoSelectLinkLabel : LinkLabel
{
public NoSelectLinkLabel()
{
// Link Label still gets focus when clicked
this.SetStyle(ControlStyles.Selectable, false);
}
}
Does anyone have any insight into how I can get this to work the way I want it to? My impression from MSDN is that doing any manipulation to the focused control in the "GotFocus", "LostFocus" and related events is a bad idea (from the "Caution" note here: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx).
Here is a crude example that shows the behavior I'm seeing:
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.AutoSi开发者_如何学PythonzeMode.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();
}
}
}
Are you trying to maintain the selection in your TextBox when it loses the focus? If so, check out TextBoxBase.HideSelection. Setting it to false will allow you to achieve that.
http://msdn.microsoft.com/en-us/library/system.windows.forms.textboxbase.hideselection.aspx
Setup some flags so that you know when you don't want the TextBox to lose it's focus, then enable the code here. This code will ignore any control attempting to take focus away. As you noted some controls ignore 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);
}
}
Update
I decided to make this into a more usable control. All the PInvoke
is intentional. There was a problem with the control not maintaining true focus. Meaning you could keep typing on the keyboard, but I fixed it with the PInvoke
and 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);
}
}
Use like this
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);
精彩评论