开发者

How to make a textbox non-selectable using C#

开发者 https://www.devze.com 2022-12-29 13:59 出处:网络
I\'m usin开发者_JS百科g C#/.NET for a Windows Forms application. I have a text box. How can I make the text box unselectable?

I'm usin开发者_JS百科g C#/.NET for a Windows Forms application. I have a text box. How can I make the text box unselectable?

I don't want to disable the complete textbox.


In the 'Enter' event of the textbox set the ActiveControl to something else:

    private void txtMyTextbox_Enter(object sender, EventArgs e)
    {
        ActiveControl = objMyOtherControl;
    }


You have a couple of options:

  1. Use a Label control instead.
  2. Set textBox.Enabled = false to prevent selection (see here).


IsHitTestVisible="False" prevents the textbox from displaying the bounding box when hovering or clicking with the mouse. That was enough in my case to take benefit of the textwrapping feature of the textbox while making it insensitive to user actions


I had the same problem. I had a dialog up and needed multiline text to be displayed. I could not use a label as it has to be a textbox because of the multiline and text wrap.

I first mad it readonly, but if the dialog is flashed by other windows, the text becomes selected which looks horrible. So I found the problem.

In the form builder program (whatever it is called), there is a property for the TextBox called TabStop. I set that to false and the read-only textbox text never gets selected. Problem solved.


Old question, and I'm not completely happy with my hack of an answer to this problem, but if the original intention was to use the text box to display data without allowing it to be selected in any way, this is a method that has (so far) worked for me.

First, the non-default properties of my text box:

Multiline        = true
ReadOnly         = true
ScrollBars       = Both
ShortcutsEnabled = false
TabStop          = false
WordWrap         = false

Then mouse event handling. Both MouseMove and DoubleClick were mapped to trigger textBox1_MouseGeneral(), and I had additional actions happening in the Click event, thus the apparent duplication of the two event handlers.

    private void MouseEvent()
    {
        textBox1.SelectionLength = 0;

        focusControl.Focus(); // Move focus to another control
    }

    private void textBox1_Click(object sender, EventArgs e)
    {
        MouseEvent();
    }

    private void textBox1_MouseGeneral(object sender, EventArgs e)
    {
        MouseEvent();
    }

You get a flash of a caret cursor, then textBox1 loses focus.


The messages that cause text can be intercepted and blocked. I would have thought that EM_SETSEL would be all that is required. However, even when the mouse clicks and drags, there is no EM_SETEL message, but the text still selects. Possibly one of the messages has a pointer to a struct that contains the info.

Note: I'm not sure if this prevents all ways to select text.

public class TextBox2 : TextBox {

    private const int EM_SETSEL = 0x00B1;
    private const int WM_LBUTTONDBLCLK = 0x203;
    private const int WM_MOUSEMOVE = 0x200;
    private const int WM_KEYDOWN = 0x100;
    private const int VK_CONTROL = 0x11;
    private const int VK_SHIFT = 0x10;

    public TextBox2() {
        this.ShortcutsEnabled = false; // disabled right click menu
        this.Cursor = Cursors.Default;

    }

    protected override void OnGotFocus(EventArgs e) {
        base.OnGotFocus(e);
        HideCaret(this.Handle); // doesn't work from OnHandleCreated
    }

    [DllImport("user32.dll")]
    public static extern bool HideCaret(IntPtr hWnd);

    public override bool PreProcessMessage(ref Message msg) {
        // prevents the user from using the SHIFT or CTRL + arrow keys to select text
        if (msg.Msg == WM_KEYDOWN)
            return true;

        return base.PreProcessMessage(ref msg);
    }

    protected override void WndProc(ref Message m) {
        if (m.Msg == EM_SETSEL || m.Msg == WM_MOUSEMOVE || m.Msg == WM_LBUTTONDBLCLK)
            return;

        base.WndProc(ref m);
    }
}


Probably the best way is to put a label behind it, and when you want to make the textbox disabled, hide it and show the label in its place.


private void textBox1_Click(object sender, EventArgs e)
        {
            this.textBox1.SelectionStart = this.textBox1.Text.Length;
        }

And don't forget that: read only=true


Try using CanFocus property.


@Mystere Man: You might want a text box that cannot be used all the time. For example, I allow the user to create text boxes on a canvas and drag them around. To prevent them from selecting and moving text when they are dragging I need to disallow user input, and text selection also needs to be disabled because it causes a delay which messes up my drag function. In my application the user can only edit a text box when he has double clicked on it, and must then click outside of the text box to be able to move it again.

I basically have this code (where t is a TextBox):

// Prevent text entry
t.IsReadOnly = true;

// Prevent text selection
t.Focusable = false;

This behaviour is preferable to disabling the whole control (t.Enabled = false), since that would also stop mousedown and doubleclick events, which would stop dragging and changing from edit to drag mode from working. Not to mention that the text box would go grey.


This has worked just fine to me:

textBox.ReadOnly = true
0

精彩评论

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

关注公众号