Textbox_KeyPress Event using vb.net or c# - c#

My requirement is i am trying to develop a text editor for my mother tongue language.
That is i am trying to develop tamil text editor using unicode characters.
When i am pressing key on the keyboard(English character like) k that time i want to replace two characters like "&H0b95" "&H0bcd".
How to i implement this concept? whether it is possible or not.
sample code when keypress event
e.keychar=chrw("&H0b95") & chrw("&H0bcd") 'This code is not Execute Becuase it get Only One Character'
TextBox1.Text=chrw("&H0b95") & chrw("&H0bcd")
I am already finish this concept but the only problem is cursor position is scroll that is when i am assigning the character to textbox that time selection start is zero so the cursor go to first position. after second line i am set the cursor position to the length of the text that is cursor come to end of the text.
so the problem is the cursor move up and down when i am pressing a key at all the times. how to solve this problem. can any body given an idea to me.
Click here! To See the Tamil Unicode Characters Table.

You need to stop the textbox from rendering, while you update the cursor position. I had done something similar before with a console application. But can't find the code to reference it here.

You need to update the SelectionStart Property and increase its length with the size of the new text inserted.
Something like:
int curPos = txtEditor.SelectionStart;
if (e.KeyChar == 'k')
{
txtEditor.Text=txtEditor.Text.Insert(txtEditor.SelectionStart, "jj");
txtEditor.SelectionLength = 0;
}
txtEditor.SelectionStart = curPos + 2; //or whatever the length of text u inserted

this TextBox, adds "jj" when the user presses k key. The cursor position is corrcted.
public class MyTextBox : TextBox
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.K)
{
int pos = this.SelectionStart;
this.Text = this.Text.Substring(0, this.SelectionStart) + "jj"
+ this.Text.Substring(this.SelectionStart);
this.SelectionStart = pos + 2;
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}

Related

How to use RichTextBox.SelectionColor property to identify multiple text's background colors in C#?

I have a RichTextBox. I'm trying to code so that if a specific color is found in the SelectionBackColor property of the RTB, the background color of the words/ texts to be removed. For that, I need to detect if there exists multiple colors in the RTB. However, according to the documentation,
If the current text selection has more than one color specified, this property returns Color.Empty.
This is what I've tried so far:
private void randomBtn_Click(object sender, EventArgs e)
{
int startIndex = 0; //start from beginning of the richTextBox1
int endIndex = this.richTextBox1.TextLength; //until the end of all text available
this.richTextBox1.Select(startIndex, endIndex); //select from start until the end
if(endIndex != 0)
{
for(int i=startIndex; i< endIndex; i++)
{
if (this.richTextBox1.Text[i].ToString().Contains(" ")) //skips white spaces
{
continue;
}
else
{
while ((this.richTextBox1.BackColor != Color.Empty))
{
if (this.richTextBox1.SelectionBackColor.R == 155 && this.richTextBox1.SelectionBackColor.G == 255 && this.richTextBox1.SelectionBackColor.B == 255)
{
this.richTextBox1.HideSelection = true; //to prevent text highlighted
MessageBox.Show(this, "Texts with RGB(155, 255, 255) found!", "", MessageBoxButtons.OK);
break;
}
else
{
this.richTextBox1.HideSelection = true;
MessageBox.Show(this, "Error!", "", MessageBoxButtons.OK);
break;
}
}
}
}
}
else
{
MessageBox.Show(this, "richTextBox1 is empty!", "Alert!", MessageBoxButtons.OK);
}
}
To test, I added a breakpoint at the code containing the while line. Below shows the success and fail criterion,
The code works if:
There is no whitespace(at all)
There is only one color in the RTB
The code fails if:
There are whitespaces in between texts/ words/ characters
There are multiple colors in the RTB
Below shows the program execution examples:
This is when only one color is applied in the RTB(success),
This is when only one color and a whitespace are applied in the RTB(fail),
This is when multiple colors and whitespaces are applied in the RTB(fail),
So, is there any ways to override the return value of the SelectionColor property to be able to detect multiple colors, or are there any other ways of doing this? Just so you know, I've searched for this kind of problem over the internet, but I didn't think I've find any related issues.
It took me a while to figure out what #TaW meant in the comment section, but thanks to him, I've managed to solve this issue.
Actually, based on my reply in the comment section that I asked #TaW, what I thought as the same concept, was actually wrong. In the post above, what I did was entirely wrong:
I was supposed to assess each text one by one to know what their colors are. However, the codes below were already wrong to begin with.:
int startIndex = 0;
int endIndex = this.richTextBox1.TextLength;
this.richTextBox1.Select(startIndex, endIndex);
To analyze how RTB.SelectionColor, RTB.SelectionStart, and RTB.SelectionLength work, I decided to create another project. The project is a simple program containing an RTB, and some other buttons to manage the RTB's SelectionColor. If you want to check for the project that I've done, you're always welcomed to visit this link.
From "2", I re-used all the codes to suit the original project that I was working on. Now, it's all fine and working as it should.
To note, there are two important concepts/ ideas on managing the Selection property of the RTB.
If you are concerned of assessing each and every text in the RTB, you should code it like this:
private void methodA(RichTextBox localRTB)
{
//go through text one by one
int startIndex = 0;
int endIndex = localRTB.TextLength;
localRTB.SelectionStart = startIndex;
localRTB.SelectionLength = 1; //always 1 'cuz we want to assess each text one by one
while (localRTB.SelectionStart < endIndex)
{
//if the SelectionBackColor is red, change it to white
if (localRTB.SelectionBackColor == Color.Red) //take red color for example
{
localRTB.SelectionBackColor = Color.White;
}
//--manage bg color of selected text in RTB--
//so that able to go to next text
localRTB.SelectionStart += 1;
}
//finally...
localRTB.DeselectAll(); //unselect text in RTB
localRTB.Select(); //set focus back to the RTB
}
Below shows the result of the codes above(1):
If you don't really care about assessing each and every text in the RTB, you should code it like this instead:
private void methodB(RichTextBox localRTB)
{
int startIndex;
int endIndex;
if (localRTB.SelectionLength.Equals(0)) //if user don't select any text
{
startIndex = 0; //from beginning of RTB
endIndex = localRTB.TextLength; //'til the end of RTB
//--manage selected text in the RTB--
localRTB.SelectionStart = startIndex;
localRTB.SelectionLength = endIndex;
localRTB.Select(localRTB.SelectionStart, localRTB.SelectionLength);
//--manage selected text in the RTB--
}
else if (!(localRTB.SelectionLength.Equals(0))) //if user has text selected
{
startIndex = localRTB.SelectionStart; //from beginning of RTB
endIndex = localRTB.SelectionLength; //'til the end of RTB
if (localRTB.SelectedText.Contains(" ")) //skips whitespaces if selected together with text
{
if (localRTB.SelectedText.EndsWith(" "))
{
endIndex -= 1;
}
}
//--manage selected text in the RTB--
localRTB.Select(startIndex, endIndex);
//--manage selected text in the RTB--
}
}
Below shows the result of the codes above(2):
Peace...✌️

SOLVED: Control-i (^i) Adding Tab in TMP_InputField

Having an issue with TextMeshPro InputField using the ASCII Character 9 (Control-i (^i) - Horizontal Tab) when I'm setting up a shortcut for Italics.
Project: Building a simple text editor using rich text tags and universal hotkeys (Office). Underline and Bold work just fine as the ASCII control functions are not inputted into the text box.
Control-b (^b) - start of text
Control-u (^u) - negative acknowledgement
Is there a way to turn off Control-i (^i) from being inputted or validate the input to not include that character. The other way I was going to do this was to use a mediator that listened to the Input class's variable inputString and changed the text of the box from there.(Not Ideal)
SOLUTION:
Found the answer to my own questions with a bit of a work around I was overlooking.
Ended up using an additional TMP_InputValidator that was toggled when either control button was held. The override class used is as follows:
public class TMP_ControlValidator : TMP_InputValidator
{
public override char Validate(ref string text, ref int pos, char ch)
{
if (char.IsControl(ch))
{
return '\0';
}
pos++;
text += ch;
return ch;
}
}

How to remove/delete Button text on when check button is clicked?

I am making this sum creator where user will have to type an answer using custom keyboard. and on check button click if answer is correct then new question is loaded.
My problem is after answering first question answer button reset to blank but when user types next answer, only one last alphabet is deleted (for example 5 from 15). and when i type 14 it shows 114 (1 from previously typed answer).
I need help to reset answer button text to blank.
I am using buttons because later i want to add more questions at the same time so user will have multiple answers to click and type.
Can anyone please help me on this? Also tell me if this is the right method to achieve what i want.
I am calling backspace function to delete previous answer and also setting text to blank.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Keyboard : MonoBehaviour
{
string word = null;
int wordIndex = -1;
string alpha = null;
string alpha2 = null;
public Text userAnswer1 = null;
public Text valueA, valueB;
public Text scoreCount;
private int a, b, answer1, score;
char[] nameChar = new char[5];
private void Start()
{
SumCreator();
}
public void nameFunc (string alphabet)
{
wordIndex++;
char[] keepchar = alphabet.ToCharArray();
nameChar[wordIndex] = keepchar[0];
alpha = nameChar[wordIndex].ToString();
word = word + alpha;
userAnswer1.text = word;
}
public void BackspaceFunction()
{
if (wordIndex >= 0)
{
wordIndex--;
alpha2 = null;
for (int i = 0; i < wordIndex + 1; i++)
{
alpha2 = alpha2 + nameChar[i].ToString();
}
word = alpha2;
userAnswer1.text = word;
}
}
public void SumCreator ()
{
a = Random.Range(0,15);
b = Random.Range(0,15);
answer1 = a + b;
valueA.text = a.ToString();
valueB.text = b.ToString();
scoreCount.text = "score " + score.ToString();
}
public void CheckAnswer()
{
Text buttonText = userAnswer1.GetComponentInChildren<Text>();
if (answer1 == int.Parse(userAnswer1.text))
{
score++;
// userAnswer1.text = string.Empty;
buttonText.text = string.Empty;
}
SumCreator();
}
}
I've edited my answer and removed the now irrelevant parts.
Once the button "Check" is clicked, first of all erase the text in the result textbox, then do the whole other logic.
To erase the text you can use next piece of code:
Text buttonText = buttonName.GetComponentInChildren<Text>();
buttonText.text = string.Empty;
You probably want to have this "buttonText" property as a global and get it once, at the start of the program instead of getting it every time the button is clicked. It won't do much difference in a small scale program, but it's a right way of thinking.
After checking your code a bit more, I can summarize your problem:
The whole logic of your program is flawed, there're many unnecessary complicated things which make it fail in several places. It is understandable, everybody goes through this stage, nothing to be ashamed or worried about. Either way it's my subjective opinion, which may be wrong.
Back to your code, all you have to do is update your result text, say "txtResult", once anything happens.
Once you click a number, do "txtResult += numberClicked".
Once you click backspace, remove last char of txtResult. Here is a question with many answers on how to do it, it's really simple.
Once you click "Check", in case it's the right number, set txtResult to empty.
Also, every time you update txtResult, you're supposed to update the UI too of course. Let's say you do it every time, it would be one line to update txtResult, and one line to update UI for each of the above 3 cases. So in total 6 lines. A check for an empty string while in "Backspace" function adds another line. My math could be wrong, but either way, it's quite short and simple approach, nothing too complicated.
You just lack relevant knowledge, otherwise you wouldn't be doing that nightmare in your Backspace function.
Regarding the "nameFunc" function, the whole 6 lines could be replaced with "txtResult += alphabet", isn't it? I'm not sure what you get in alphabet parameter, but either way, string is an array of chars, so you can also do "txtResult += alphabet[0]" instead of what you have there.
So, in total, you got it all right, the logic was right, you figured the main aspects. But you over complicated the whole thing. I believe you'll be fine after reading all this text, and wish you the best.
If you want to clear your Text object when you have succesfully entered your answer, you should not call your "BackSpace" function.
Just replace your code to this:
if (answer1 == int.Parse(userAnswer1.text))
{
score++;
userAnswer1.text = string.Empty;
This will clear the text element.
You could also look into using InputFields in Unity, which are designed for entering input and automatically support backspace and other keyboard functions.
If you do, make sure that you set the InputField's ContentType to either Integer Number or Decimal Number

TextBox for product code - handling the dashes

I have a TextBox where a user is meant to enter a product code that looks like this:
XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
What I'm trying to do is automatically placing the dashes in the right place as the user is typing, so that they only have to enter the actual code itself (similar to what's done in various pieces of software).
The problems I'm encountering have got to do with the position of the cursor as the user is typing.
My current solution (partially working) is as the following:
private void textBoxProductKey_KeyPress(object sender, KeyPressEventArgs e)
{
if (char.IsControl(e.KeyChar))
{
return;
}
if (!char.IsLetterOrDigit(e.KeyChar) || textBoxProductKey.Text.Length == 29)
{
e.Handled = true;
return;
}
var cursorPosition = textBoxProductKey.SelectionStart;
string text;
if (cursorPosition == 0)
{
text = e.KeyChar + textBoxProductKey.Text;
}
else if (cursorPosition == textBoxProductKey.Text.Length)
{
text = textBoxProductKey.Text + e.KeyChar;
}
else
{
text = textBoxProductKey.Text.Insert(cursorPosition, e.KeyChar.ToString());
}
text = Regex.Replace(text, "-", "");
text = Regex.Replace(text, ".{5}", "$0-");
textBoxProductKey.Text = text.Length <= 29 ? text : text.Substring(0, 29);
textBoxProductKey.SelectionStart = cursorPosition / 6 == (cursorPosition + 1) / 6
? cursorPosition + 1
: cursorPosition + 2;
e.Handled = true;
}
The two problems with my current solution are
It doesn't properly handle the delete/backspace keys where potentially the dashes need to be deleted/inserted in different locations and the cursor position re-calculated
It doesn't work properly if the cursorPosition == textBoxProductKey.Text.Length.
The latter is very easy to fix, but I'm struggling with the former and also feel like the code is a bit convoluted.
How can I more easily achieve this (note the plan is to continue using a TextBox object).
EDIT
I am aware of the MaskedTextBox control, I do not want to use a MaskedTextBox, I want to use a TextBox.
What I am trying to do is not outside the realms of possibility for a TextBox, even if there are "easier" ways to accomplish this with other controls.
Also I feel like this is a great question for teaching people how to work with the cursor in a TextBox (among other things probably).
Have you considered using the MaskedTextBox control? It might be more appropriate.
The MaskedTextBox is designed precisely for this type of requirement and would answer your original question.
You may find it more difficult to implement this functionality yourself with a normal TextBox. It's also worth weighing up which solution is more likely to be be bug-free and easier to maintain.
It may helpful if you could to explain to us why you would prefer use a TextBox over a MaskedTextBox.
Continuing our conversation, save your current caret position, parse the whole text as if it's new, and return the caret to its original position.
That way you handle deleting as well as copy-pasting

In form numberpad C#

I would like to add an in form numberpad to my form to make the program more touch friendly. I have multiple text boxes on this form that change focus when the enter key is pressed.
I tried SendKeys.Send("#"), but when I click the button it just changes focus to the button and does nothing inside the text box I was trying to type in.
Is there a guide or something for this? I have looked and all I can find are on screen keyboards that work outside of the form, but not inside.
Expanding a little bit on the idea from Hans Passant you could use this as a starting point.
Form
In your form add the textboxes you need and a PictureBox. The picturebox will have an image with the characters your users need to be able to type.
Set the property Image to an image file (browse for it) (or create your own)
Set the property SizeMode to AutoSize so the complete picture is shown.
Next goto the events and add an eventhandler for MouseClick.
Code
Add the following code to the handler:
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
// how many rows and columns do we have
// in the picture used
const int maxrows = 4;
const int maxcols = 3;
// based on each position (numbered from left to right, top to bottom)
// what character do we want to add the textbox
var chars = new [] {'1','2','3','4','5','6','7','8','9', '+', '0', '-'};
// on which row and col is clicked, based on the mouse event
// which hold the X and Y value of the coordinates relative to
// the control.
var row = (e.Y * maxrows) / this.pictureBox1.Height;
var col = (e.X * maxcols) / this.pictureBox1.Width;
// calculate the position in the char array
var scancode = row * maxcols + col;
// if the active control is a TextBox ...
if (this.ActiveControl is TextBox)
{
// ... add the char to the Text.
// add error and bounds checking as well as
// handling of special chars like delete/backspace/left/right
// if added and needed
this.ActiveControl.Text += chars[scancode];
}
}
The code is I think self explanatory. Keep in mind that no error checking whatsoever is being done here.
Result
This is what the end result will look like:

Categories

Resources