例如:
你好(在这里插入:D)这是一条消息
结果是:
你好,这是一条消息☺<<图片 另一个(微小的)问题是插入后的插入位置在插入之前设置. 这就是我已经得到的:
public class Emoticon { public Emoticon(string key, Bitmap bitmap) { Key = key; Bitmap = bitmap; BitmapImage = bitmap.ToBitmapImage(); } public string Key { get; } public Bitmap Bitmap { get; } public BitmapImage BitmapImage { get; } } public class EmoticonRichTextBox : RichTextBox { private readonly List<Emoticon> _emoticons; public EmoticonRichTextBox() { _emoticons = new List<Emoticon> { new Emoticon(":D", Properties.Resources.grinning_face) }; } protected override void OnTextChanged(TextChangedEventArgs e) { base.OnTextChanged(e); Dispatcher.InvokeAsync(Look); } private void Look() { const string keyword = ":D"; var text = new TextRange(Document.ContentStart, Document.ContentEnd); var current = text.Start.GetInsertionPosition(LogicalDirection.Forward); while (current != null) { var textInRun = current.GetTextInRun(LogicalDirection.Forward); if (!string.IsNullOrWhiteSpace(textInRun)) { var index = textInRun.IndexOf(keyword, StringComparison.Ordinal); if (index != -1) { var selectionStart = current.GetPositionAtOffset(index, LogicalDirection.Forward); if (selectionStart == null) continue; var selectionEnd = selectionStart.GetPositionAtOffset(keyword.Length, LogicalDirection.Forward); var selection = new TextRange(selectionStart, selectionEnd) { Text = string.Empty }; var emoticon = _emoticons.FirstOrDefault(x => x.Key.Equals(keyword)); if (emoticon == null) continue; var image = new System.Windows.Controls.Image { Source = emoticon.BitmapImage, Height = 18, Width = 18, Margin = new Thickness(0, 3, 0, 0) }; // inserts at the end of the line selection.Start?.Paragraph?.Inlines.Add(image); // doesn't work CaretPosition = CaretPosition.GetPositionAtOffset(1, LogicalDirection.Forward); } } current = current.GetNextContextPosition(LogicalDirection.Forward); } } } public static class BitmapExtensions { public static BitmapImage ToBitmapImage(this Bitmap bitmap) { using (var stream = new MemoryStream()) { bitmap.Save(stream, ImageFormat.Png); stream.Position = 0; var image = new BitmapImage(); image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.DecodePixelHeight = 18; image.DecodePixelWidth = 18; image.StreamSource = stream; image.EndInit(); image.Freeze(); return image; } } }错误的行是选择.启动?.Paragraph?.Inlines.Add(image);.您将图像追加到段落的末尾.您应该使用InsertBefore或InsertAfter方法之一.
但是要使用这些方法,您应该遍历Inlines并找到要在之前或之后插入的正确内联.这并不困难.您可以通过将selectionStart和selectionEnd与内联的ElementStart和ElementEnd属性进行比较来确定内联.
另一个棘手的可能性是您要插入的位置可能属于内联.然后你应该拆分内联并创建其他三个:
>一个包含插入位置之前的元素
>一个包含图像
>一个包含插入位置后的元素.
然后,您可以删除内联并将新的三个内联插入到正确的位置.
Wpf的RichTextBox没有最漂亮的API.有时可能很难使用.还有一个名为AvalonEdit的控件.它比RichTextBox更容易使用.你可能想要考虑一下.