11

I have a textbox with the following (important) properties:

this.license.Multiline = true;
this.license.ReadOnly = true;
this.license.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.license.ShortcutsEnabled = false;

It looks like this:

Textbox with highlighted text in it

How can I disable the user to highlight text in this textbox (I do not want to disable the textbox completely)?

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Victor
  • 13,914
  • 19
  • 78
  • 147

13 Answers13

12

Attach to the SelectionChanged event, and inside the event set e.Handled = true; and the SelectionLength = 0; and that will stop the selection from occuring. This is similar to what it takes to keep a key press from happening.

Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
  • 13
    I couldn't find such event for the WinForms TextBox control. – checho Jan 07 '14 at 12:15
  • 4
    @checho In case you're interested, I ran into the same issue as you but resolved it by using the WinForms RichTextBox control, which thankfully does have the `SelectionChanged` event. – Calcolat Sep 10 '15 at 07:05
  • 2
    Doing this with a TextBox results in an recursive loop and StackOverflowException. Changing the selection inside the SelectionChanged callback is a bad idea! – floydheld Jan 16 '19 at 10:37
  • @floydheld You can unregister the hander right before the SelectionAll and again register it right after to prevent the StackOverflowException. – Lukáš Koten Oct 13 '20 at 16:47
9

If you put the text into a label and then put the label into a System.Widnows.Forms.Panel control that has AutoScroll turned on you can display the text w/o it being selectable.

JG in SD
  • 5,427
  • 3
  • 34
  • 46
8

To disable selection highlight in a TextBox, you can override WndProc and handle WM_SETFOCUS message and replace it with a WM_KILLFOCUS. Please be aware that it doesn't make the TextBox control read-only and if you need to make it read-only, you should also set ReadOnly property to true. If you set ReadOnly to true, you can set and its BackColor to White or any other suitable color which you want.

In below code, I added a SelectionHighlightEnabled property to MyTextBox to make enabling or disabling the selection highlight easy:

  • SelectionHighlightEnabled: Gets or sets a value indicating selection highlight is enabled or not. The value is true by default to act like a normal TextBox. If you set it to false then the selection highlight will not be rendered.
using System.ComponentModel;
using System.Windows.Forms;
public class MyTextBox : TextBox
{
    public MyTextBox()
    {
        SelectionHighlightEnabled = true;
    }
    const int WM_SETFOCUS = 0x0007;
    const int WM_KILLFOCUS = 0x0008;
    [DefaultValue(true)]
    public bool SelectionHighlightEnabled { get; set; }
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_SETFOCUS && !SelectionHighlightEnabled)
            m.Msg = WM_KILLFOCUS;

        base.WndProc(ref m);
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Works well. You might also want to change the `Cursor` to Default (instead of the text selection IBeam pointer). – intrepidis Jul 28 '22 at 12:30
  • @intrepidis Thanks; makes sense. In addition, since it doesn't make the control read-only, if you need to make it read-only, you should also set ReadOnly property to true and also you may want to set BackColor to White in case of enabling read-only. – Reza Aghaei Jul 28 '22 at 13:15
  • The input cursor disappeared for me – Thomas Weller Jan 26 '23 at 22:29
2

I came across of this thread for my same issue I faced. Somehow I resolved it as below,

if (sender != null)
                {
                    e.Handled = true;
                    if((sender as TextBox).SelectionLength != 0)
                        (sender as TextBox).SelectionLength = 0;
                }

Verifying if the length changed other than 0, then only set it to 0, resolves the recursive loop.

Minaketan
  • 21
  • 2
1

Since the standard TextBox doesn't have the SelectionChanged event, here's what I came up with.

private void TextBox1_MouseMove(object sender, MouseEventArgs e)
{
    TextBox1.SelectionLength = 0;
}
clamchoda
  • 4,411
  • 2
  • 36
  • 74
  • Also for a better solution, you can add events to clamchoda [answer](https://stackoverflow.com/a/53607577/9819238) like: `MouseLeave` and `KeyPress` MouseLeave for deselecting when the mouse is no longer in the textbox area and KeyPress is for deselecting when the user press the Shift + Key Up/Down for selection. – Death GOD 7 Dec 22 '21 at 13:15
1

Very Easy Solution

Find a Label and into the textbox go to mousedown event and set focus to the label

This is in VB and can be easily converted into C#

Private Sub RichTextBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles RichTextBox1.MouseDown
        Label1.Focus()
    End Sub
Adam
  • 147
  • 1
  • 13
0

You can use a disabled RichTextBox and reset the color to black afterwards.

RichTextBox rtb = new RichTextBox();
rtb.IsEnabled = false;
rtb.Text = "something";
rtb.SelectAll();
rtb.SelectionColor = Color.Black;
rtb.SelectedText = String.Empty;
Onominous
  • 19
  • 6
sean.net
  • 735
  • 8
  • 25
0

If you are using XAML / WPF you should use a TextBlock instead of a TextBox.

ONLY IF YOU USE A TEXTBOX AS A DISPLAY AND NOT FOR INPUT - as TextBlock makes it seem as if the text is "engraved" onto the form itself, and not within a textbox. To get a Border around the TextBlock (if you wish), you can either do it :

In XAML such as :

<Border BorderThickness="1" BorderBrush="Gray">
    <TextBlock Background="White" Text="Your Own TextBlock"/>
</Border>

Or dynamically in C# Code:

//Create a Border object
Border border = new Border();
border.BorderThickness = new Thickness(1);
border.BorderBrush = Brushes.Black;

//Create the TextBlock object           
TextBlock tb = new TextBlock();
tb.Background = Brushes.White;
tb.Text = "Your Own TextBlock";

//Make the text block a child to the border
border.Child = tb;
Onominous
  • 19
  • 6
iato
  • 356
  • 5
  • 16
0

For multiline text, a label won't do. My solution is to set the Enter event on the textbox and redirect the focus elsewhere. E.g.

    private void textBox1_Enter(object sender, EventArgs e)
    {
        this.anotherControl.Focus(); // Preferably a readonly control in case the user starts typing
    }
Skyfish
  • 119
  • 2
  • 4
-1

In WinForms, the correct method is to assign the event MouseMove and set the SelectionLength to 0.

I´ve tried here and works perfectly.

elixenide
  • 44,308
  • 16
  • 74
  • 100
-1
private void textBox5_Click(object sender, EventArgs e)
{
    this.textBox5.SelectionStart = this.textBox5.Text.Length;
}
Bart
  • 9,925
  • 7
  • 47
  • 64
-1

I know this is an old question, but the correct and simple answer is :

SelectionOpacity = 0;

this works for both TextBox and RichTextBox in WPF.

Maria
  • 344
  • 8
  • 30
-1

guys!

Fell free to try this solution: first, create a derived class from original RichTextBox. In the constructor, set Selectable and UserMouse style flags:

public class MyRichTextBox : RichTextBox
{
    public MyRichTextBox()
    {
        SetStyle(ControlStyles.Selectable, false);
        SetStyle(ControlStyles.UserMouse, true);
    }
}

Then, use it instead of original:

private void InitializeComponent()
{
    ...
    this.richTextBox1 = new MyRichTextBox();
    ...

Also, you can set those behaiour flags, to avoid unnessesery user interactions:

this.richTextBox1.Cursor = System.Windows.Forms.Cursors.Default;
this.richTextBox1.ReadOnly = true;
this.richTextBox1.ShortcutsEnabled = false;