zoukankan      html  css  js  c++  java
  • c# – RichTextBox用表情符号/图像替换字符串

    在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<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更容易使用.你可能想要考虑一下.

  • 相关阅读:
    关于前端输入框的限制和有效值
    js,jquery转json的几种方法
    java,js,jstl,EL的简单交互
    mysql字段冲突报错
    js的一些压缩和优化性能
    一个不错的html素材网站
    redis之数据操作详解
    redis之持久化操作
    redis之django-redis
    redis知识总汇
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14782054.html
Copyright © 2011-2022 走看看