如何在单击时阻止LinkLabel控件获得焦点?

时间:2011-01-03 21:22:55

标签: .net winforms

我需要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();
        }
    }
}

2 个答案:

答案 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都是故意的。控件没有保持真正的焦点存在问题。这意味着你可以继续在键盘上打字,但我用PInvokeFocus()修复了它。

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);
相关问题