开发者

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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜