Hi well my problem is this
I have a RichTextBox but i wanna add a "pretty" space after the paragraph, i found on the internet many examples but all examples change all the lines and not only the paragraph.
private void FormatRTB(byte rule, int space, int x)
{
PARAFORMAT fmt = new PARAFORMAT();
fmt.cbSize = Marshal.SizeOf(fmt);
fmt.dwMask = PFM_LINESPACING;
fmt.dyLineSpacing = space;
fmt.bLineSpacingRule = rule;
richTextBox1.Select(x, 2);
SendMessage(new HandleRef(richTextBox1, richTextBox1.Handle),
EM_SETPARAFORMAT,
SCF_SELECTION,
ref fmt
);
}
Well i add this code and select ony the \n because after of "\n" start the paragraph and dosent works i dont if my logic is bad or i need to add more code
while (richTextBox1.Text.IndexOf("\n", k) > 0)
{
k = richTextBox1.Text.IndexOf("\n", k);
setLineFormat(2, 0, k);
k++;
}
.
I know that there is already an accepted answer, but maybe this will help other people.
If you really want to add spacing before or after a paragraph in RichTextBox, there is a very simple and "native" (ie. no hacking) solution using PFM_SPACEBEFORE or PFM_SPACEAFTER. The code is quite similar to the first one you present.
The complete solution with a custom control is posted on http://dominicweb.eu/en/blog/various/winforms-richtextbox-with-paragraph-spacing-csharp/
If you are sure that all the occurrences of "\n" are indeed a different paragraph, you can simply add spaces after it. You could use a simple loop as:
for (int i = 0; i < richTextBox1.Text.Length; i++)
{
if (richTextBox1.Text[i] == '\n')
richTextBox1.Text.Insert(i + 1, " ");
}
Often though paragraphs are marked with both '\n' and '\r' so you may look for the \r instead
Related
I am playing with C#. I try to write program that frames the quote entered by a user in a square of chars. So, the problem is... a user needs to indicate the number of lines before entering a quote. I want to remove this moment, so the user just enters lines of their phrase (each line is a new element in the string array, so I guess a program should kinda declare it by itself?..). I hope I explained clear what I meant x).
I've attached the program code below. I know that it is not perfect (for example, when entering the number of lines, I use the conversion to an integer, and if a user enters a letter, then this may confuse my electronic friend, this is a temporary solution, since I do not want to ask this x) The program itself must count these lines! x)) Though, I don't understand why the symbols on the left side are displayed incorrectly when the program displays output, but I think this also does not matter yet).
//Greet a user, asking for the number of lines.
Console.WriteLine("Greetings! I can put any phrase into beautiful #-square."
+ "\n" + "Wanna try? How many lines in the quote: ");
int numberOfLines = Convert.ToInt32(Console.ReadLine());
//Asking for each line.
string[] lines = new string[numberOfLines];
for (int i = 0; i < numberOfLines; i++)
{
Console.WriteLine("Enter the line: ");
lines[i] = Console.ReadLine();
}
//Looking for the biggest line
int length = 0;
for (int i = 0; i < numberOfLines; i++)
{
if (length < lines[i].Length) length = lines[i].Length;
}
//Starting framing
char doggy = '#';
char space = ' ';
length += 4;
string frame = new String(doggy, length);
Console.WriteLine(frame);
for (int i = 0; i < numberOfLines; i++)
{
string result = new string(space, length - 3 - lines[i].Length);
Console.WriteLine(doggy + space + lines[i] + result + doggy);
}
Console.WriteLine(frame);
Console.ReadLine();
}
}
}
There is performance gap and functionality between "Generic Lists" and arrays, you can read more about cons and pros of this two objects in the internet,
for example you can use list as Dai mentioned in comment like this
List<string> list = new List<string>();
list.Add("one");
list.Add("two");
list.Add("three");
or you can use arraylist
ArrayList arraylist = new ArrayList();
arraylist.Add();
or even you can change the size of array any times but it erase data in it
int[] arr = new int[100];
there is a function called ToArray() you can use it to change generic list to array
Your problem of the left side output is, that you add two values of char. This is not what you expect to be. You must convert the char to a string to append it to other strings:
Console.WriteLine(doggy.ToString() + space.ToString() + lines[i] + result + doggy.ToString());
I am trying to make a simple WYSIWYG editor. I found pretty difficult to format the rtb.
It is supposed to format basic things like bold, italic, coloring(and mixed).
What have I found and tried so far:
private void boldButton_Click(object sender, EventArgs e)
{
int start = rtb.SelectionStart;
int length = rtb.SelectionLength;
for (int i = start, max = start + length; i < max; ++i)
{
rtb.Select(i, 1);
rtb.SelectionFont = new Font(rtb.Font, rtb.SelectionFont.Style | FontStyle.Bold);
}
rtb.SelectionStart = start;
rtb.SelectionLength = length;
rtb.Focus();
}
rtb = richtextbox.
This works as expected, but is terribly slow.
I also found the idea about using and formatting directly the RTF, but the format seems too complicated and very easy to mistake it.
I hope it is a better solution.
Thank you.
The performance hit is probably down to the fact you're looping through each character instead of doing everything in one go:
var start = this.rtb.SelectionStart;
var length = this.rtb.SelectionLength;
this.rtb.Select(start, length);
this.rtb.SelectionFont = new Font(this.rtb.Font, this.rtb.SelectionFont.Style | FontStyle.Bold);
I've had the same problem myself. Interestingly, I found out that you can speed up formatting by an order of magnitude if you refrain from referencing to the control's properties when looping through. Instead, put the necessary control properties in separate variables before entering the loop. For instance, instead of continuously referencing e.g. richTextBox1.Length, replace with int len = richTextBox1.Length, and then refer to len inside the loop. Instead of referencing to richTextBox1.Text[index], replace with string text = richTextBox1.Text before the loop, and then instead text[index] inside the loop.
I am in the process of learning C# and I'm building a hangman game from scratch as one of my first projects.
Everything works except for the part that replaces the dashes of the hidden word with the correctly guessed letters.
For example: ----- becomes G-EA- after you guess G, E, and A.
I have a for loop that logically seems like it'd do the job except I can't use the == operator for strings or chars.
for (int i = 0; i <= answer.Length; i++) //answer is a string "theword"
{
if (answer[i] == passMe) //passMe is "A" for example
{
hiddenWord = hiddenWord.Remove(i, 1);
hiddenWord = hiddenWord.Insert(i, passMe);
}
}
I've scoured the net trying to find a good solution. Most recommend using Regex or other commands I haven't learned yet and therefore don't fully understand how to implement.
I've tried converting both to char format in the hope that it would fix it, but no luck so far. Thanks in advance for any help.
If passMe is a string of only one char then
if (answer[i] == passMe[0])
In this way you compare the character at i-th position with the character at the first position of your user input
There is also a serious error in your code.
Your loop goes off by one, change it to
for (int i = 0; i < answer.Length; i++)
The arrays in NET start at index zero and, the max index value possible, is always one less than the length of the array.
answer[i] refers to a character and passMe is a single character string. (not a character)
Try this
for (int i = 0; i <= answer.Length; i++) //answer is a string "theword"
{
if (answer[i] == passMe[0]) //passMe is "A" for example
{
hiddenWord = hiddenWord.Remove(i, 1);
hiddenWord = hiddenWord.Insert(i, passMe);
}
}
you need to compare a character with a character.
i'm looking for a way to select text between two lines (A and B) in a richtextbox.
I tried something like this:
richTextBox1.Select
(
richTextBox1.GetFirstCharIndexFromLine(parentesi_inizio[current_idx]),
(
richTextBox1.GetFirstCharIndexFromLine(parentesi_fine[current_idx]) -
richTextBox1.GetFirstCharIndexFromLine(parentesi_inizio[current_idx]) + 1
)
);
Inside parentesi_inizio and parentesi_fine i have the line number, i should select from line A (parentesi_inizio) to B (parentesi_fine).
After some tests i think the problem is this:
richTextBox1.GetFirstCharIndexFromLine(parentesi_fine[current_idx]) -
richTextBox1.GetFirstCharIndexFromLine(parentesi_inizio[current_idx]) + 1
This code works fine at first, but I noticed that after a while 'begins to show results stoner.
I did further testing and the lines are correct (ie, refer to the right spot) whereas "Select" does not select the entire portion or does it incorrectly (selecting parts that do not have to)
( I used google translate for the last part )
EDIT:
Imagine this text:
Hello
World || A points here (Line 1)
Guys!
This
is
a || B points here (Line 5)
line
I need to Select (not get text) this text:
World
Guys!
This
is
a
in the richtextbox.
Example images:
Case 1:
Case 2:
Thats is what i want and what the code i posted do, but after a while the code starts to bug as i said above (at the start).
EDIT 2:
I changed my code to this after varocarbas reply
richTextBox1.Select (
richTextBox1.GetFirstCharIndexFromLine(parentesi_inizio[current_idx]),
richTextBox1.GetFirstCharIndexFromLine(parentesi_inizio[current_idx])
+ count_length(parentesi_inizio[current_idx], parentesi_fine[current_idx]) );
where count_length is
private int count_length(int A, int B)
{
// A => first line
// B => last line
int tot = 0;
for (int i = A; i <= B; ++i)
{
// read the length of every line between A and B
tot += richTextBox1.Lines[i].Length - 1;
}
// return it
return tot;
}
but now the code not work in every case.. anyway here is a screen of a bugged case using the old code (the code posted at the start of the question)
(source: site11.com)
it select right from the first { but not reach the last } (i do some checks here and the problem is the subtraction not the lines num.)
EDIT 3:
I'm ready sorry varocarbas, i think i just wasted your time.. after see my screen i noticed the problem might be the word wrap i tried to disable it and seems now works ok.. sorry for your time.
Why not relying on the lines[] array directly?
string line2 = richTextBox1.lines[1];
Bear in mind that it has its own indexing, that is, to get the first character in the third line you can do:
int firstChar3 = richTextBox1.lines[2].Substring(0, 1);
To refer to the whole richTextBox indexing system, you can rely also on GetFirstCharIndexFromLine. That is:
int startIndexLine2 = richTextBox1.GetFirstCharIndexFromLine(1); //Start index line2
int endIndexLine2 = startIndexLine2 + richTextBox1.lines[1].length - 1; //End index line2
-------- AFTER UPDATED QUESTION
Sorry about that, but I cannot see the code in the links you provided. But the code below should deliver the outputs you want:
int curStart = richTextBox1.GetFirstCharIndexFromLine(2);
richTextBox1.Select(curStart, richTextBox1.Lines[2].Length);
string curText = richTextBox1.SelectedText; -> "Guys!"
curStart = richTextBox1.GetFirstCharIndexFromLine(3);
richTextBox1.Select(curStart, richTextBox1.Lines[3].Length);
curText = richTextBox1.SelectedText; -> "This"
curStart = richTextBox1.GetFirstCharIndexFromLine(4);
richTextBox1.Select(curStart, richTextBox1.Lines[4].Length);
curText = richTextBox1.SelectedText; -> "is"
I'm making a game, and I read dialogue text from an XML file. I'm trying to make a routine to add in newlines automatically as needed, so that it fits in the text box. It just won't work right, though. Here's the code as it currently is:
SpriteFont dialogueFont = font31Adelon;
int lastSpace = 0;
string builder = "";
string newestLine = "";
float maxWidth = 921.6f;
float stringLength = 0;
for (int i = 0; i <= speech.Length - 1; i++) //each char in the string
{
if (speech[i] == ' ') //record the index of the most recent space
{
lastSpace = i;
}
builder += speech[i];
newestLine += speech[i];
stringLength = dialogueFont.MeasureString(newestLine).X;
if (stringLength > maxWidth) //longer than allowed
{
builder = builder.Remove(lastSpace); //cut off from last space
builder += Environment.NewLine;
i = lastSpace; //start back from the cutoff
newestLine = "";
}
}
speech = builder;
My test string is "This is an example of a long speech that has to be broken up into multiple lines correctly. It is several lines long and doesn't really say anything of importance because it's just example text."
This is how speech ends up looking:
http://www.iaza.com/work/120627C/iaza11394935036400.png
The first line works because it happens to be a space that brings it over the limit, I think.
i = 81 and lastSpace = 80 is where the second line ends. builder looks like this before the .Remove command:
"This is an example of a long speech that\r\nhas to be broken up into multiple lines c"
and after it is run it looks like this:
"This is an example of a long speech that\r\nhas to be broken up into multiple line"
The third line goes over the size limit at i = 123 and lastSpace = 120. It looks like this before the .Remove:
"This is an example of a long speech that\r\nhas to be broken up into multiple line\r\ncorrectly. It is several lines long and doe"
and after:
"This is an example of a long speech that\r\nhas to be broken up into multiple line\r\ncorrectly. It is several lines long an"
As you can see, it cuts off an extra character, even though character 80, that space, is where it's supposed to start removing. From what I've read .Remove, when called with a single parameter, cuts out everything including and after the given index. It's cutting out i = 79 too, though! It seems like it should be easy enough to add or subtract from lastSpace to make up for this, but I either get "index out of bounds" errors, or I cut off even more characters. I've tried doing .Remove(lastSpace, i-lastSpace), and that doesn't work either. I've tried handling "ends with a space" cases differently than others, by adding or subtracting from lastSpace. I've tried breaking things up in different ways, and none of it has worked.
I'm so tired of looking at this, any help would be appreciated.
You add Environment.NewLine to your StringBuilder, you need to consider that when you specify the index where to start removing.
Environment.NewLine's value is System dependent. It can be "\r\n", "\n" or "\r" (or, only one of the first two according to MSDN).
In your case it's "\r\n", that means for removing one space, you added two other characters.
First, you need to declare a new variable:
int additionalChars = 0;
Then, when adding a line of text, you should change your code to something like this:
builder = builder.Remove(lastSpace + additionalChars); //cut off from last space
builder += Environment.NewLine;
additionalChars += Environment.NewLine.Length - 1;
The -1 is because you already removed a space (should make this code independent of the system's definition of Environment.NewLine).
UPDATE: You should also account for words that are longer than the line limit. You should break them anyway (couldn't help but have a try):
if (stringLength > maxWidth) //longer than allowed
{
// Cut off only if there was a space to cut off at
if (lastSpace >= 0) {
builder = builder.Remove(lastSpace + additionalChars); //cut off from last space
i = lastSpace; //start back from the cutoff
}
builder += Environment.NewLine;
// If there was no space that we cut off, there is also no need to subtract it here
additionalChars += Environment.NewLine.Length - (lastSpace >= 0 ? 1 : 0);
lastSpace = -1; // Means: No space found yet
newestLine = "";
}
As an alternative approach, you could break your sentence up into an array using .split and then fill your box until there isn't space for the next work, then add the newline and start on the next line.
Can you do something like the following code. The advantage is two-fold. Firstly, it skips to the next space to measure and decide whether to add the whole word or not, rather than going letter by letter. Secondly, it only calls MeasureString once for each word in the string, rather than for every letter added to the string. It uses StringBuilder with Append when the word will fit, or AppendLine when it won't fit and a new-line needs to be added.
int lastSpace = 0;
int nextSpace = s.IndexOf(' ', lastSpace + 1);
float width = 0;
float totalWidth = 0;
float maxWidth = 200;
while (nextSpace >= 0)
{
string piece = s.Substring(lastSpace, nextSpace - lastSpace);
width = g.MeasureString(piece, this.Font).Width;
if (totalWidth + width < maxWidth)
{
sb.Append(piece);
totalWidth += width;
}
else
{
sb.AppendLine(piece);
totalWidth = 0;
}
lastSpace = nextSpace;
nextSpace = s.IndexOf(' ', lastSpace + 1);
}
MessageBox.Show(sb.ToString());