so i have a string of characters that are typically formatted like this:
" text" where the bold character is red.
i want to display these types of strings in a richtextbox with the bold character being red.
i have the text in a string variable and i have the location of the red character (in the string) in an int variable.
my solution is:
get characters before the red character
get red character
get characters after the red character
display characters before the red character
display red character (with foreground = Brushes.Red)
display characters after the red characters
this is what i've got so far:
https://github.com/icebbyice/rapide/blob/master/rapide/SpreadWindow.xaml.cs
find: "//stackoverflow" (also, seperateOutputs is not completed)
i stopped there because i thought there had to be a more efficient way to do it because i will be changing the content of the rich text box often (up to 1000 content changes / 60 seconds).
so, is there a better way to do this?
You could do this:
// getting keywords/functions
string keywords = #"\b(e)\b";
MatchCollection keywordMatches = Regex.Matches(codeRichTextBox.Text, keywords);
// saving the original caret position + forecolor
int originalIndex = codeRichTextBox.SelectionStart;
int originalLength = codeRichTextBox.SelectionLength;
Color originalColor = Color.Black;
// MANDATORY - focuses a label before highlighting (avoids blinking)
menuStrip1.Focus();
// removes any previous highlighting (so modified words won't remain highlighted)
codeRichTextBox.SelectionStart = 0;
codeRichTextBox.SelectionLength = codeRichTextBox.Text.Length;
codeRichTextBox.SelectionColor = originalColor;
// scanning...
foreach (Match m in keywordMatches)
{
codeRichTextBox.SelectionStart = m.Index;
codeRichTextBox.SelectionLength = m.Length;
codeRichTextBox.SelectionFont = new Font(codeRichTextBox.Font, FontStyle.Bold);
}
// restoring the original colors, for further writing
codeRichTextBox.SelectionStart = originalIndex;
codeRichTextBox.SelectionLength = originalLength;
codeRichTextBox.SelectionColor = originalColor;
codeRichTextBox.SelectionFont = new Font(codeRichTextBox.Font, FontStyle.Regular);
// giving back the focus
codeRichTextBox.Focus();
That belongs in the RichTextBox TextChanged Event
If you type e, it will display it Bold. Any other text will be displayed as Font.Regular
If you would like to change the syntax from e, then look at the keywords string
This is all I have for this, I hope it helps you :)
Related
I have a Winform application in C# that is doing mail merge from a DataGridView.
I need to merge a checked/unchecked box for a Boolean cell.
String strPresent;
char EmptyBox = (char)0xA8;
char CheckedBox = (char)0x254;
Boolean bPresent = (Boolean)selectedRow.Cells["Present"].Value;
if (bPresent)
strPresent = CheckedBox.ToString();
else
strPresent = EmptyBox.ToString();
In the Word mergefields processing code:
case "Present":
myMergeField.Select();
wordApp.Selection.TypeText(strPresent);
wordApp.Selection.MoveLeft(WdUnits.wdCharacter, 1, WdMovementType.wdExtend);
Everything works to this point:
The problem is the checkbox is formatted Calibri (Body), not Wingdings.
wordApp.Selection.Font.Name = "Wingdings";
break;
The mergefield in the template is already formatted as Wingdings.
I have tried * charformat instead of * mergeformat in the template.
I have added a trailing underscore and a space to prevent the Selection.TypeText from selecting the whole paragraph.
Making the Word process visible, I can see the correct character is selected.
I've also tried:
Range myRange = wordApp.Selection.Range;
myRange.Font.Name = "Wingdings";
I tried changing this:
char EmptyBox = (char)0xA8;
char CheckedBox = (char)0x254;
to this:
char EmptyBox = Char.Parse("\u2610");
char CheckedBox = Char.Parse("\u2611");
and now I see a checkbox, but it appears narrow horizontally?
I am building a report using StringBuilder and the details of it to be properly intended and aligned
for which i will be using
private static int paperWidth = 55; //it defines the size of paper
private static readonly string singleLine = string.Empty.PadLeft(paperWidth, '-');
StringBuilder reportLayout;
reportLayout.AppendLine("\t" + "Store Name");
I want Store Name in center and many such more feilds by use of \t
Thanks in Advance.
EDIT
I want to print like. Store Name in center
If you're simulating what tabs look like at a terminal you should
stick with 8 spaces per tab. A Tab character shifts over to the next
tab stop. By default, there is one every 8 spaces. But in most shells
you can easily edit it to be whatever number of spaces you want
You can realize this through the following Code:
string tab = "\t";
string space = new string(' ', 8);
StringBuilder str = new StringBuilder();
str.AppendLine(tab + "A");
str.AppendLine(space + "B");
string outPut = str.ToString(); // will give two lines of equal length
int lengthOfOP = outPut.Length; //will give you 15
From the above example we can say that in .Net the length of \t is
calculated as 1
A Tab is a Tab and its meaning is created by the application that renders it.
Think of a word processor where a Tab means:
Go to the next tab stop.
You can define the tab stops!
To center output do not use Tabs, use the correct StringFormat :
StringFormat fmt = new StringFormat()
{ Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
This centers the text inside a rectanlge in both directions:
e.Graphics.DrawString(someText, someFont, someBrush, layoutRectangle, fmt);
or something like it..
But it looks as if you want to embed the centering inside a text.
This will only work if you really know everything about the output process, i.e. the device, the Font and Size as well as the margins etc..
So it will probably not be reliable at all, no matter what you do.
The best alternative may be to either give up on plain text or use a fixed number of spaces to 'mean' 'centered' and then watch for this number when you render.
If you don't have control over the rendering, it will not work.
I'm using a RichTextBox for coloured text. Let's assume I want to use different colours for different portions of the text. This is working fine so far.
I'm currently having a problem with the SelectionStart property of the RichTextBox. I've set some text to the Text property of the RichTextBox. If the text contains \r\n\r\n the SelectionStart Position won't match the position of characters with the assigned String.
Small example (WinformsApplication. Form with a RichTextBox):
public Form1()
{
InitializeComponent();
String sentence1 = "This is the first sentence.";
String sentence2 = "This is the second sentence";
String text = sentence1 + "\r\n\r\n" + sentence2;
int start1 = text.IndexOf(sentence1);
int start2 = text.IndexOf(sentence2);
this.richTextBox1.Text = text;
String subString1 = text.Substring(start1, sentence1.Length);
String subString2 = text.Substring(start2, sentence2.Length);
bool match1 = (sentence1 == subString1); // true
bool match2 = (sentence2 == subString2); // true
this.richTextBox1.SelectionStart = start1;
this.richTextBox1.SelectionLength = sentence1.Length;
this.richTextBox1.SelectionColor = Color.Red;
this.richTextBox1.SelectionStart = start2;
this.richTextBox1.SelectionLength = sentence2.Length;
this.richTextBox1.SelectionColor = Color.Blue;
}
The RichTextBox looks like this:
As you can see, the first two characters of the second sentence are not coloured. This is the result of an offset produced by \r\n\r\n.
What is the reason for this? Should I use another control for colouring text?
How do I fix the problem in a reliable way? I've tried replacing the "\r\n\r\n"with a String.Empty, but that produces other offset problem.
Related question:
Inconsistent behaviour between in RichTextBox.Select with SubString method
It seems that the sequence \r\n counts for one character only when doing selections. You can do the measurements in a copy of the string where all \r\n are replaced by \n.
Just for completeness (I'll stick to linepogls answer for now):
I've found another way to get indices for the SelectionStart property. The RichTextBox offers a Find method, that can be used to retrieve index positions based on a specified string.
Be aware of the fact, that the text you want to highlight might not be unique and occur multiple times. You can use an overload to specify a start position for the search.
I'm working on a custom RichTextBox which highlights certain words typed in it.
(more like highlight certain strings, because I intent to highlight strings that are not separated by spaces)
I search for strings by loading the text to memory, and looking for a list of strings one by one, then applying formatting to them.
Issue is that, index I get from the plain text representation, doesn't necessarily point to the same position in the RichTextBox's content, when formatting is applied.
(First formatting is perfect. Any subsequent formatting starts to slip to the left. I assume this is because formatting adds certain elements to the documents which makes my indexes incorrect.)
Sample pseudo code for this is as follows.
// get the current text
var text = new TextRange(Document.ContentStart, Document.ContentEnd).Text;
// loop through and highlight
foreach (string entry in WhatToHighlightCollection)
{
var currentText = text;
var nextOccurance = currentText.IndexOf(suggestion); //This index is Unreliable !!!
while (nextOccurance != -1)
{
// Get the offset from start. (There appears to be 2 characters in the
// beginning. I assume this is document and paragraph start tags ??
// So add 2 to it.)
int offsetFromStart = (text.Length) - (currentText.Length) + 2;
var startPointer = Document.ContentStart.
GetPositionAtOffset(offsetFromStart + nextOccurance, LogicalDirection.Forward);
var endPointer = startPointer.GetPositionAtOffset(suggestion.Length, LogicalDirection.Forward);
var textRange = new TextRange(startPointer, endPointer);
textRange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow));
textRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
textRange.ApplyPropertyValue(TextElement.FontFamilyProperty, new FontFamily("Segoe UI"));
// Go to the next occurance.
currentText = currentText.Substring(nextOccurance + suggestion.Length);
nextOccurance = currentText.IndexOf(suggestion);
}
}
How do I map string indexes to rich text box content ?
NOTE: I'm not worried about the performance of this at the moment, although any suggestions are always welcome, as currently I run this on every TextChanged event to highlight 'as the user type' and it's getting a bit sluggish.
well, the title pretty much says it all.
here's a little info:
i have a text file, and inside that textfile contains:
Label
"this text will be associated with the Text property of the label once the label has been added to the Panel Control at runtime."
20, 45
Trebuchet MS
14.0
explanation of the above
the above file may have only one label-info, or it may have a thousand of them. here's how it works:
Control
Text Property
Locatoin
Font Name
Font Size
...Now, all is well if i leave out the font information from the file. but as soon as i modified my regex to suit for the font name and font size, my program no longer adds the control to the Panel at runtime. there are no debugging errors or ugly squigly lines either. It just doesn't show anything.
So, my guess is the last part of the regex that tries to match font information/ can somebody please help me understand/solve this problem?
the code i have is:
public partial class Form1 : Form
{
private void FillCanvas()
{
canvas.Controls.Clear();
canvas.Visible = true;
canvas.BringToFront();
txt.Visible = false;
MatchCollection lines = Regex.Matches(File.ReadAllText(Path), #"(.+?)\r\n""([^""]+)""\r\n(\d+), (\d+)\r\n""(\w*)\r\n" +
#"(\d+)");
foreach (Match match in lines)
{
string control = match.Groups[1].Value;
string text = match.Groups[2].Value;
int x = Int32.Parse(match.Groups[3].Value);
int y = Int32.Parse(match.Groups[4].Value);
string fname = match.Groups[6].Value;
float fsize = float.Parse(match.Groups[7].Value);
switch (control)
{
case "Label":
Label label = new Label();
label.Text = text;
label.AutoSize = true;
label.IsAccessible = true;
label.Font = new Font(fname, fsize);
label.MouseMove += new MouseEventHandler(label_MouseMove);
label.MouseDown += new MouseEventHandler(label_MouseDown);
label.MouseUp += new MouseEventHandler(label_MouseUp);
label.Click += new EventHandler(label_Click);
label.DoubleClick += new EventHandler(label_DoubleClick);
canvas.Controls.Add(label);
ControlCount++;
label.Name = ControlCount.ToString();
label.Location = new Point(x, y);
SelectedControl = label.Name;
break;
Your regex pattern is incorrect. Change it to this:
#"(.+?)\r\n""([^""]+)""\r\n(\d+),\s(\d+)\r\n([\w\s]*)\r\n(\d+)"
Your original pattern has 2 problems when it attempts to match the font name. First, it has unnecessary quotation marks, but there are none for the font name section. Second, the font name can have a space in it, and your pattern didn't account for it.
Your pattern:
#"(.+?)\r\n""([^""]+)""\r\n(\d+), (\d+)\r\n""(\w*)\r\n(\d+)"
^ ^
| |
1st problem ___| |
2nd problem ___|
BTW, the current pattern does not correctly capture the "14.0" font size. It will capture "14" only. If you need to capture the rest of it, consider using (\d+(?:\.\d+)?) instead if it's an optional format. If you always expect it to be in that format then use (\d+\.\d+).
EDIT: if it's within your control I suggest switching the text file / regex approach to an XML format instead. Some nice LINQ to XML will make this simpler to maintain.
Have you set a breakpoint inside the foreach and debugged? Since you are iterating over the results of a MatchCollection, the first place I'd check is to see if you have zero matches.