Is there any way to disable cursor in textbox without setting property Enable to false?
I was trying to use ReadOnly property but despite the fact that I can't write in textbox, the cursor appears if I click the textbox. So is there any way to get rid of this cursor permamently?
In C#, you can use the following read-only textbox:
public class ReadOnlyTextBox : TextBox
{
[DllImport("user32.dll")]
static extern bool HideCaret(IntPtr hWnd);
public ReadOnlyTextBox()
{
this.ReadOnly = true;
this.BackColor = Color.White;
this.GotFocus += TextBoxGotFocus;
this.Cursor = Cursors.Arrow; // mouse cursor like in other controls
}
private void TextBoxGotFocus(object sender, EventArgs args)
{
HideCaret(this.Handle);
}
}
In C# you can disable the cursor in a textbox by temporarily disabling and then re-enabling the text box whenever it receives the focus. Note there is no need to make the textbox read only if using this method. For example:
private void TextBox_Enter(object sender, EventArgs e)
{
TextBox.Enabled = false;
TextBox.Enabled = true;
}
You could use a Label instead. When in the designer, you set BorderStyle = Fixed3D, BackColor = Window and AutoSize = False, it looks a lot like a TextBox.
However, the cursor in a TextBox is provided so that the user can scroll through the text when it is longer than the box. You'll lose that functionality with a Label, unless you are sure that it will always fit. Other than that, it is not possible to remove the cursor from a TextBox.
Putting the hideCaret function inside the TextChanged event will solve the problem:
[DllImport("user32.dll")]
static extern bool HideCaret(IntPtr hWnd);
private void textBox1_TextChanged(object sender, EventArgs e)
{
HideCaret(textBox1.Handle);
}
Easiest solution for me was to just override the on focus event and focus back to the parent. This prevents the cursor and any editing of the textbox by the user and basically disables the text box with out having to set the Enabled = false property.
private void Form1_load(object sender, EventArgs e) {
textBox1.ReadOnly = true;
textBox1.Cursor = Cursors.Arrow;
textBox1.GotFocus += textBox1_GotFocus;
}
private void textBox1_GotFocus(object sender, EventArgs e) {
((TextBox)sender).Parent.Focus();
}
Like #Mikhail Semenov 's solution, you can also use lambda express to quickly disable the cursor if you do not have many textboxes should do that:
[DllImport("user32.dll")]
static extern bool HideCaret(IntPtr hWnd);
textBox1.ReadOnly = true;
textBox1.BackColor = Color.White;
textBox1.GotFocus += (s1, e1) => { HideCaret(textBox1.Handle); };
textBox1.Cursor = Cursors.Arrow;
You can set it programatically.
textBox1.Cursor = Cursors.Arrow;
This is not strictly an answer to the question, but perhaps it can solve some similar problem(s). I use a textbox control which can look like a label for a control which displays a scale, but can be edited, when clicked. Start enabled = false and make an activation (enabled = true) in a mousehandler of the parent of the textbox control (which, when disabled, border None and backcolor = parent backcolor, looks like a label). E.g. when enter hit or other event, disable again in KeyDown handler.
(Of course the parent mouse click routine can check whether the mouseclick really occured in the label/textbox control).
If you need the textbox control to activate by tabbing, some more work is required (than I have done).
I use the form constructor to find the textbox parent at runtime and to apply the delegate mouse control. Perhaps you can do this as wel in compile time (Form header), but that seemed a little error-prone to me.
One way of doing it is using View + TabIndex, you can do indexing of some other controls on the dialog as first, let say for buttons if there any. Then as if the control tabIndex is not the first i.e 0, cursor won't get appear there.
To disable the edit and cursor in the TEXT BOX
this.textBox.ReadOnly = true;
this.textBox.Cursor = Cursors.No;//To show a red cross icon on hover
this.textBox.Cursor = Cursors.Arrow //To disable the cursor
you can use RightToLeft Property of Text Box, set it to true, you will not get rid of the Cursor, but it will get fixed at right corner and it will not appear automatically after every text you type in your text Box. I have used this to develop an application like Windows Calculator.
Related
I am trying to show a MessageBox (or something that I can put text into) when the context Help Button in the Form's Tile Bar is pressed.
This is the help button I want pressed:
Any help would be great! :)
A few additions to what has already been posted.
The Help Button is shown in the Caption of a Form.
To activate it, set HelpButton = true, MinimizeBox = false and MaximizeBox = false.
The HelpButtonClicked event is raised, for the Form only, when the Help Button is clicked.
The HelpRequested event is raised when you click on a Control after (when the Mouse Pointer has the shape of a question mark).
To show Help related to a Control, you can subscribe to the HelpRequested event of each Control that provides Help, or you can use just the Form's HelpRequested event for all Controls.
You need to get the child Control that was selected when the Mouse is clicked.
Here I'm using WindowFromPoint() to get the handle of the Control at the position specified by HelpEventArgs.
This function can get the handle of nested Controls.
A Dictionary<Control, string> is used to store and retrieve the Help text for all Controls that should provide a description of their functionality (or whatever else).
The Help text can of course come from localized Project Resources.
Note that the Help is not generated for ContainerControls (the Form itself, Panel, GroupBox etc.) and WindowFromPoint doesn't get the handle of disabled Controls.
using System.Runtime.InteropServices;
public partial class SomeForm : Form
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr WindowFromPoint(Point point);
Dictionary<Control, string> help = new Dictionary<Control, string>();
public SomeForm() {
InitializeComponent();
help.Add(someButton, "Help on someButton");
help.Add(someTextBox, "someTextBox gets help");
help.Add(someNestedControl, "someNestedControl needs clarifications");
}
private void SomeForm_HelpButtonClicked(object sender, CancelEventArgs e) {
// The Help Button has been clicked
}
private void SomeForm_HelpRequested(object sender, HelpEventArgs e) => ShowHelp(e);
public void ShowHelp(HelpEventArgs e) {
e.Handled = true;
var ctl = FromHandle(WindowFromPoint(e.MousePos));
if (ctl != null && help.ContainsKey(ctl)) {
MessageBox.Show(help[ctl]);
}
else {
MessageBox.Show("No help for this Control");
}
}
}
You need to wire up the HelpRequested or HelpButtonClicked events
Plus you need to get the button shown (off by default on a form) by setting
HelpButton = true
MinimizeBox = false
MaximizeBox = false
Sounds like you're new to C# so I'll give you the most simple rundown I can with examples:
In the InitializeComponent() function you need to add:
HelpRequested += new System.Windows.Forms.HelpEventHandler(this.form_helpRequested);
This will tell the form to run form_helpRequested once the help button is pressed. Then you can implement this event handler function with:
private void textBox_HelpRequested(object sender, System.Windows.Forms.HelpEventArgs hlpevent)
{
// Your code here
// Example of a popup with text:
MessageBox.Show("This is a help popup");
}
This all needs to be in your Form1.cs (or equivilent) script.
For reference on this event handler, I'd suggest giving this article a read: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.helprequested?view=windowsdesktop-6.0
To show the relevant information(in monopoly game, the property belongs which player, current market price etc.), I put a Label on the top of a panel, and used a ToolTip object to display the information. This is the image of my current setup.
Here are the steps I have done:
1.Added MouseHover event handler (The Label name is MEDITERANEAN)
this.MEDITERANEAN.MouseHover += new System.EventHandler(this.MEDITERANEAN_MouseHover);
2.Initialized Tooltip
private void InitializeToolTip()
{
toolTipLabel.ToolTipIcon = ToolTipIcon.Info;
toolTipLabel.IsBalloon = true;
toolTipLabel.ShowAlways = true;
}
3.Call setToolTip() in MouseHover call back function
private void MEDITERANEAN_MouseHover(object sender, EventArgs e)
{
toolTipLabel.SetToolTip(MEDITERANEAN, "You put mouse over me");
rolledDice.AppendText("Mouse Over");
}
But when I start application and move my cursor over the label, there is no text from toolTipLabel. What part did I make mistakes?
Interestingly, i made other function and it works.
private void panelBoard_MouseOver(object sender, EventArgs e)
{
toolTipLabel.SetToolTip(panelBoard, "You put mouse over me");
rolledDice.AppendText("Mouse Over");
}
I think you just need to bring your lable control in front of image. Try something like this .
MEDITERANEAN.BringToFront();
I found the solution, first I should set Panel's property "Enable" to true, then set label's property "visible" to true as well.
I'm making a settings form, where user can assign custom hotkeys for the application. There's a TextBox, and by clicking it with mouse, it focuses and waits for one keypress and then defocuses (by focusing another label):
private void txtKey_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
}
private void txtKey_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
TextBox textBox = (TextBox)sender;
textBox.Text = e.KeyCode.ToString();
label1.Focus();
}
Is there a way to defocus focused TextBox (and cancel the key assinging process), by either clicking it again with mouse, or by clicking the GroupBox around it? I can't figure out how to check if TextBox was already focused when clicked (because when clicked, it gets focused before I can test if it's focused). Of course I can add a button "Cancel" next to the TextBox, but that's not what I want.
There is no Click-event for GroupBox, so I can't defocus TextBox by clicking GroupBox around it. Or can I somehow?
You can set/remove the Focus with
Keyboard.Focus = null;
You can also register to the following event:
public event MouseButtonEventHandler PreviewMouseLeftButtonDown
This event fires every time you click on the TextBox, thus you can set the Focus there if you want to.
For Winforms there is a way as well. I'm not proficient in it, but here would be a way:
Make a textBox (e.g. named textBoxFocus) that lies outside your window. Size it 1, 1 and move it to -10,-10 for example. Then you can register to the Click event and write
textBoxFocus.Focus();
It's a bit of a roundabout way, but should achieve what you want.
Thanks to private_meta for getting me to right direction (in comments)! I set the flag with click event, and before setting the flag, testing if flag is set. So first click does not find the flag, but second will. And flag is cleared within textbox Enter-event (which fires before Click-event). Now every other click focuses and every other defocuses textbox, as I wanted.
private void txtKey_Enter(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
textBox.Tag = null;
}
private void txtKey_Click(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
if (textBox.Tag != null) label1.Focus();
textBox.Tag = "clicked";
}
One of the simple way is that, you may use a bool flag here.
Algorithm:
By default, the bool value is 0;
If(Textbox Selected && flag = 0)
Do your task; and flag = 1;
I hope I could satisfy your query and you can follow this algorithm.
I have a TextBox which is set to be ReadOnly.
At some point that TextBox is being available for editing, and it's BackColor changes (It is indicating if the value is valid).
If I want to set the TexBox back to ReadOnly, the TextBox doesn't get back the original BackColor that a ReadOnly TextBox gets.
What should I do in order to get the original color again?
I realize I can set the color manually to SystemColors.Control, but is this the "right way"?
Code Sample
This is a simple code for demonstration.
If SystemColors.Control is the way to go, I will change it in the ReadOnlyChanged event...
private void button1_Click(object sender, EventArgs e)
{
//At this point this.textBox1 is ReadOnly
this.textBox1.ReadOnly = false;
this.textBox1.BackColor = Color.Orange;
/*this.textBox1.BackColor = SystemColors.Control;*/ //Is this the right way?
this.textBox1.ReadOnly = true; //Textbox remains orange...
}
You have to set BackColor to the look of a ReadOnly TextBox's BackColor, that is Color.FromKnownColor(KnownColor.Control):
//this is the ReadOnlyChanged event handler for your textbox
private void textBox1_ReadOnlyChanged(object sender, EventArgs e){
if(textBox1.ReadOnly) textBox1.BackColor = Color.FromKnownColor(KnownColor.Control);
}
You may need a variable to store the current BackColor every time your TextBox's BackColor changes:
Color currentBackColor;
bool suppressBackColorChanged;
private void textBox1_BackColorChanged(object sender,EventArgs e){
if(suppressBackColorChanged) return;
currentBackColor = textBox1.BackColor;
}
private void textBox1_ReadOnlyChanged(object sender, EventArgs e){
suppressBackColorChanged = true;
textBox1.BackColor = textBox1.ReadOnly ? Color.FromKnownColor(KnownColor.Control) : currentBackColor;
suppressBackColorChanged = false;
}
I know this is an old question, but for posterity sake:
TextBox as well as many other controls rely on Color.Empty to decide whether or not to display its default color.
To set a TextBox back to the system default (irregardless of state):
textBox1.BackColor = Color.Empty;
Yes, that's fine. There's no reason you can't use the SystemColors to specify the desired color for the control. I've never heard of anything in WinForms that would cause a control to automatically revert to its default color upon setting ReadOnly = true.
I suppose one alternative is to create a class-level variable called textBox1OriginalColor or something and set it in the form's Load event. Then you know exactly what it was when the form was originally displayed, if you think someone might in the future set the text box's default background color to, say, blue in the designer or something.
The question is simple: how to do it?
I've a couple of MaskedTextboxes which are filled by some indirect user actions (so not by typing in values directly). The text within the textboxes is colored red when the input is being rejected by the mask. Fine so far.
However, I don't want the end-user to be able to edit the boxes directly. So, I added the following code:
private void HandleMaskedTextBoxKeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = true;
}
private void HandleMaskedTextBoxKeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
e.SuppressKeyPress = true;
}
And while most characters are handled, the backspace and delete keys aren't: text disappears when pressing those keys. How can those keys be handled, too?
(Another option would be to set the readonly property of the boxes to true, but then the text doesn't get colored red anymore when input is rejected. I tried to force the red color in the MaskInputRejected event, but this didn't work out, either.)
I think it's a good idea to set the MaskedTextBox's ReadOnly property to true. But instead of handling the MaskInputRejected event, you should use the TypeValidationCompleted event like this:
private void maskedTextBox1_TypeValidationCompleted(object sender, TypeValidationEventArgs e) {
maskedTextBox1.ForeColor = e.IsValidInput ? Color.Black : Color.Red;
}
Since I guess you're modifying the value of the MaskedTextBox by code, you'll have to also handle the TextChanged event to trigger a validation like this:
private void maskedTextBox1_TextChanged(object sender, EventArgs e) {
maskedTextBox1.ValidateText();
}
Finally (and this is key), since the MaskedTextBox will be read only, you'll want to set the BackColor and ForeColor properties back to Color.White and Color.Black respectively, but you'll have to do it in code, in the constructor of the form for instance...
maskedTextBox1.BackColor = Color.White;
maskedTextBox1.ForeColor = Color.Black;
If you have a lot of them, I suggest you create a new control that inherits from MasketTextBox and override those values.
You can use a richtextbox. Set read only to true, and mask the chars with the code beind.
I hope that helps.
RG