在RichtTextBox中,我想用表情符号图像自动替换表情符号字符串(例如:D).
我到目前为止工作,除了当我在现有的单词/字符串之间写出表情符号字符串时,图像会在行尾插入.
例如:
你好(在这里插入: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
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更容易使用.你可能想要考虑一下.
手机扫一扫
移动阅读更方便
你可能感兴趣的文章