Re: WPF RichTextBox Question
Your best bet is to pull all the content out into an array list or list of strings do the formatting their and then build a flow document (which is what the RTB uses) each time. That way your RUN's are re writen each time. Also rather than loop through the runs you could just apply some REGEX queries to replace each smilie code with the inline code for the given smilie. Im in work at the moment but I will post some code on how to do that later (around 7pm) for ya!
Re: WPF RichTextBox Question
Ok so I need to find out what exactly which way you are doing what your doing. So in your application do I type into a text box and then you update the RTB? Give me a run through and Il give you a hand?
Re: WPF RichTextBox Question
On self input yes. Say I type in "Hello! :P" and my font I have selected is Tahoma and the color is black it will pass the folowing string to be formatted to the rtb.
[style co:#000000;b;]Tewl : [/style][style ff:Tahoma;co:#000000]Hello! :P[/style]
Re: WPF RichTextBox Question
Ok sorry this took so long, I was playing with code. Now if you are using an RTB for your input box and another RTB for your "display" you do not need to use style tags or anything else for that matter. Consider that a flow document is simply a Xaml rendering control. This means that its content is all written in Xaml. Xaml is of course text. So if we use this nifty piece of code which is basically your method 1 extended:
Code:
Dim tr As New TextRange(PasteBox.Document.ContentStart, PasteBox.Document.ContentEnd)
Dim ms As New MemoryStream
tr.Save(ms, DataFormats.Xaml)
Dim TextArray As String = ASCIIEncoding.Default.GetString(ms.ToArray())
and text array now contains an array of your text with the Xaml mark-up included as a plain string. the content is already grouped with a section object from what I can gather from tests. So you would simply need to add this array as a section to your display window.
Now because you have the FULL power of flow documents you can now do something that most messengers cant do. you can make fantasticly rich content. so smilies embedded video, fancy lists! This all of course depends on your server construction but it is all technically possible. have fun with it!
Re: WPF RichTextBox Question
Re: WPF RichTextBox Question
Re: WPF RichTextBox Question
I'm kinda of lost as to how to insert images and clickable urls with this method
Re: WPF RichTextBox Question
This is the flow document class. If you look towards the end you will see the different classes you can use with a flow document. The ones you need to look at is link and inline ui container.
Re: WPF RichTextBox Question
I was having an issue understanding the TextPointers but I think I have it now.
Code:
private void button1_Click(object sender, EventArgs e)
{
TextRange tr = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
TextPointer stp = rtb.Document.ContentStart.GetPositionAtOffset(tr.Text.Length - 2);
tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
tr.Text = "\rSome :) text here";
tr.ApplyPropertyValue(TextElement.ForegroundProperty, System.Windows.Media.Brushes.Black);
tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
tr.Text = "\rSome more text :) here";
tr.ApplyPropertyValue(TextElement.ForegroundProperty, System.Windows.Media.Brushes.Red);
tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
tr.Text = "\rmore text here :)";
tr.ApplyPropertyValue(TextElement.ForegroundProperty, System.Windows.Media.Brushes.SteelBlue);
BitmapImage bi;
tr = new TextRange(stp, rtb.Document.ContentEnd);
string emoticonText = GetEmoticonText(tr.Text);
TextPointer tp = stp;
while (emoticonText != string.Empty)
{
while (!tp.GetTextInRun(LogicalDirection.Forward).StartsWith(emoticonText))
tp = tp.GetNextInsertionPosition(LogicalDirection.Forward);
tr = new TextRange(tp, tp.GetPositionAtOffset(emoticonText.Length));
tr.Text = string.Empty;
bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(mappings[emoticonText]);
bi.DecodePixelWidth = 26;
bi.EndInit();
System.Windows.Controls.Image image = new System.Windows.Controls.Image();
image.Width = 26;
image.Stretch = System.Windows.Media.Stretch.None;
image.Source = bi;
new InlineUIContainer(image, tp);
tr = new TextRange(tp, rtb.Document.ContentEnd);
if (tr.Text == string.Empty)
break;
else
emoticonText = GetEmoticonText(tr.Text);
}
}
private string GetEmoticonText(string text)
{
string match = string.Empty;
int lowestPosition = text.Length;
foreach (KeyValuePair<string, string> pair in mappings)
{
if (text.Contains(pair.Key))
{
int newPosition = text.IndexOf(pair.Key);
if (newPosition < lowestPosition)
{
match = pair.Key;
lowestPosition = newPosition;
}
}
}
return match;
}
I am curious as to why this returns a length of 2 when the RTB is empty.
TextRange tr = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
MessageBox.Show(tr.Text.Lengh.ToString());
Other than that, now all I have to do is write a function to convert urls tp clickable hyperlinks.
Re: WPF RichTextBox Question
Ok my next issue with this is putting in the Hyperlinks
Code:
string uriText = GetUriText(tr.Text);
Hyperlink h;
while (uriText != string.Empty)
{
while (!tp.GetTextInRun(LogicalDirection.Forward).StartsWith(uriText))
tp = tp.GetNextInsertionPosition(LogicalDirection.Forward);
h = new Hyperlink(tp, tp.GetPositionAtOffset(uriText.Length));
tp = tp.GetPositionAtOffset(uriText.Length);
tr = new TextRange(tp, rtb.Document.ContentEnd);
if (tr.Text != string.Empty)
uriText = GetUriText(tr.Text);
}
Code:
private string GetUriText(string text)
{
string match = string.Empty;
Regex r = new Regex("(?:^|[\\s\\[\\]\\}\\{\\(\\)\\\'\\\"<>])((?:(?:https?|gopher|ftp|file|irc):\\/\\/|www\\.)[a-zA-Z0-9\\.\\-=;&%\\?]+(?:\\/?[a-zA-Z0-9\\.\\-=;&%\\?]*)*)");
if (r.IsMatch(text))
{
Match m = r.Match(text);
match = m.Groups[1].Value;
}
return match;
}
After I run this I get a squiggly line under the url but it is not clickable nor does it fire any events when I add a click event to the hyperlink object.
Re: WPF RichTextBox Question
Screenshot: Removed bandwidth issue
Re: WPF RichTextBox Question
Hmmmm, something is breaking your Links alright. You need to pull the xaml out and have a look to see if they are being created properly.
Re: WPF RichTextBox Question
hmmm. I'm kind of lost as to what to do at this point.
Code:
<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve" TextAlignment="Left" LineHeight="Auto" IsHyphenationEnabled="False" xml:lang="en-us" FlowDirection="LeftToRight" NumberSubstitution.CultureSource="User" NumberSubstitution.Substitution="AsCulture" FontFamily="Microsoft Sans Serif" FontStyle="Normal" FontWeight="Normal" FontStretch="Normal" FontSize="11" Foreground="#FF000000" Typography.StandardLigatures="True" Typography.ContextualLigatures="True" Typography.DiscretionaryLigatures="False" Typography.HistoricalLigatures="False" Typography.AnnotationAlternates="0" Typography.ContextualAlternates="True" Typography.HistoricalForms="False" Typography.Kerning="True" Typography.CapitalSpacing="False" Typography.CaseSensitiveForms="False" Typography.StylisticSet1="False" Typography.StylisticSet2="False" Typography.StylisticSet3="False" Typography.StylisticSet4="False" Typography.StylisticSet5="False" Typography.StylisticSet6="False" Typography.StylisticSet7="False" Typography.StylisticSet8="False" Typography.StylisticSet9="False" Typography.StylisticSet10="False" Typography.StylisticSet11="False" Typography.StylisticSet12="False" Typography.StylisticSet13="False" Typography.StylisticSet14="False" Typography.StylisticSet15="False" Typography.StylisticSet16="False" Typography.StylisticSet17="False" Typography.StylisticSet18="False" Typography.StylisticSet19="False" Typography.StylisticSet20="False" Typography.Fraction="Normal" Typography.SlashedZero="False" Typography.MathematicalGreek="False" Typography.EastAsianExpertForms="False" Typography.Variants="Normal" Typography.Capitals="Normal" Typography.NumeralStyle="Normal" Typography.NumeralAlignment="Normal" Typography.EastAsianWidths="Normal" Typography.EastAsianLanguage="Normal" Typography.StandardSwashes="0" Typography.ContextualSwashes="0" Typography.StylisticAlternates="0"><Paragraph><Run>
Some </Run><Run> </Run><Run> text here</Run><Run Foreground="#FFFF0000">
Some </Run><Hyperlink Foreground="#FF808080" TextDecorations="Underline"><Run Foreground="#FFFF0000">http://www.microsoft.com</Run></Hyperlink><Run Foreground="#FFFF0000"> more text </Run><Run> </Run><Run Foreground="#FFFF0000"> here</Run><Run Foreground="#FF4682B4">
more text here </Run><Run> </Run></Paragraph></Section>
Re: WPF RichTextBox Question
I see the issue, your link doesnt have a navigateuri in it it only has text. see this http://msdn.microsoft.com/en-us/libr...hyperlink.aspx for usage.
Re: WPF RichTextBox Question
I get the same result if I set the NavigateUri as well
Code:
h = new Hyperlink(tp, tp.GetPositionAtOffset(uriText.Length));
h.NavigateUri = new Uri(uriText);
Code:
<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve" TextAlignment="Left" LineHeight="Auto" IsHyphenationEnabled="False" xml:lang="en-us" FlowDirection="LeftToRight" NumberSubstitution.CultureSource="User" NumberSubstitution.Substitution="AsCulture" FontFamily="Microsoft Sans Serif" FontStyle="Normal" FontWeight="Normal" FontStretch="Normal" FontSize="11" Foreground="#FF000000" Typography.StandardLigatures="True" Typography.ContextualLigatures="True" Typography.DiscretionaryLigatures="False" Typography.HistoricalLigatures="False" Typography.AnnotationAlternates="0" Typography.ContextualAlternates="True" Typography.HistoricalForms="False" Typography.Kerning="True" Typography.CapitalSpacing="False" Typography.CaseSensitiveForms="False" Typography.StylisticSet1="False" Typography.StylisticSet2="False" Typography.StylisticSet3="False" Typography.StylisticSet4="False" Typography.StylisticSet5="False" Typography.StylisticSet6="False" Typography.StylisticSet7="False" Typography.StylisticSet8="False" Typography.StylisticSet9="False" Typography.StylisticSet10="False" Typography.StylisticSet11="False" Typography.StylisticSet12="False" Typography.StylisticSet13="False" Typography.StylisticSet14="False" Typography.StylisticSet15="False" Typography.StylisticSet16="False" Typography.StylisticSet17="False" Typography.StylisticSet18="False" Typography.StylisticSet19="False" Typography.StylisticSet20="False" Typography.Fraction="Normal" Typography.SlashedZero="False" Typography.MathematicalGreek="False" Typography.EastAsianExpertForms="False" Typography.Variants="Normal" Typography.Capitals="Normal" Typography.NumeralStyle="Normal" Typography.NumeralAlignment="Normal" Typography.EastAsianWidths="Normal" Typography.EastAsianLanguage="Normal" Typography.StandardSwashes="0" Typography.ContextualSwashes="0" Typography.StylisticAlternates="0"><Paragraph><Run>
Some </Run><Run> </Run><Run> text here</Run><Run Foreground="#FFFF0000">
Some </Run><Hyperlink Foreground="#FF808080" NavigateUri="http://www.microsoft.com" TextDecorations="Underline"><Run Foreground="#FFFF0000">http://www.microsoft.com</Run></Hyperlink><Run Foreground="#FFFF0000"> more text </Run><Run> </Run><Run Foreground="#FFFF0000"> here</Run><Run Foreground="#FF4682B4">
more text here </Run><Run> </Run></Paragraph></Section>
Re: WPF RichTextBox Question
Try remove the runs manually and then put the xaml code back into the RTB via a section and see does it click then I think they are causing the issue.
Re: WPF RichTextBox Question
Doing that removes all of the formatting
Re: WPF RichTextBox Question
I know but for the moment we just need to find out if it is affecting the click ability of the link.
Re: WPF RichTextBox Question
Same result. Link is now grey. Updated screenshot above.
Re: WPF RichTextBox Question
and still not clickable. This may sound stupid but try to control click the link. Otherwise im out of ideas for the moment.
Re: WPF RichTextBox Question
I apparently the click event wouldnt fire. MouseLeftButtonDown however does. This fixes my main issue, now I just have to figure out how to insert the hyperlink to to text that is split into 2 seperate runs
<Run>http://www.micro</Run><Run>soft.com</Run>
Code:
tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
tr.Text = "\rSome http://www.micro";
tr.ApplyPropertyValue(TextElement.ForegroundProperty, System.Windows.Media.Brushes.Red);
tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
tr.Text = "soft.com more text :) here";
tr.ApplyPropertyValue(TextElement.ForegroundProperty, System.Windows.Media.Brushes.SteelBlue);
Re: WPF RichTextBox Question
One of your objects is not initialised. IE
MyVar VAR = new VAR;
Re: WPF RichTextBox Question
It's the TextPointer that is null; it becomes null during the loop.
Re: WPF RichTextBox Question
I was experimenting with a new method of inserting the text and managed to get this which works really well altho it doesn't fix my issue with inserting urls that are in 2 different Runs but that is a minor issue.
Code:
private void InsertHyperlink(TextPointer position)
{
string match = string.Empty;
Regex r = new Regex("(?:^|[\\s\\[\\]\\}\\{\\(\\)\\\'\\\"<>])((?:(?:https?|gopher|ftp|file|irc):\\/\\/|www\\.)[a-zA-Z0-9\\.\\-=;&%\\?]+(?:\\/?[a-zA-Z0-9\\.\\-=;&%\\?]*)*)");
Hyperlink h;
while (position != null)
{
if (position.CompareTo(this.Document.ContentEnd) == 0)
{
break;
}
if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
String text = position.GetTextInRun(LogicalDirection.Forward);
Int32 indexInRun = -1;
if (r.IsMatch(text))
{
Match m = r.Match(text);
match = m.Groups[1].Value;
indexInRun = m.Groups[1].Index;
}
if (indexInRun >= 0)
{
position = position.GetPositionAtOffset(indexInRun);
h = new Hyperlink(position, position.GetPositionAtOffset(match.Length));
h.Tag = match;
h.Foreground = Brushes.Blue;
h.TextDecorations = TextDecorations.Underline;
h.Cursor = System.Windows.Input.Cursors.Hand;
h.MouseLeftButtonDown += new MouseButtonEventHandler(h_MouseLeftButtonDown);
position = position.GetPositionAtOffset(match.Length);
}
else
{
position = position.GetPositionAtOffset(text.Length);
}
}
else
{
position = position.GetNextContextPosition(LogicalDirection.Forward);
}
}
}