Search code examples
wpftextcopyrichtextboxemoticons

Copying emoticon "text" from a richtextbox showing image in wpf


I am looking for a good, clean way to enable copying of text from a richtextbox displaying emoticons. Think of skype, where you can select a chat and it will copy the emoticon images and convert them to their textual representations (smiley image to :) etc). I am using the MVVM pattern.


Solution

  • I don't know of a way to configure the parsing of RichTextBox content to text. Below is one way which uses xml linq. Regular expressions might work better but I suck at them. Pass ConvertToText method teh FLowDocument of your RichTextBox.

    private static string ConvertToText(FlowDocument flowDocument)
    {
        TextRange textRangeOriginal =
            new TextRange(flowDocument.ContentStart, flowDocument.ContentEnd);
    
        string xamlString;
        using (MemoryStream memoryStreamOriginal = new MemoryStream())
        {
            textRangeOriginal.Save(memoryStreamOriginal, DataFormats.Xaml);
            xamlString = ASCIIEncoding.Default.GetString(memoryStreamOriginal.ToArray());
        }
    
        XElement root = XElement.Parse(xamlString);
    
        IEnumerable<XElement> smilies =
            from element in root.Descendants()
            where (string)element.Attribute("FontFamily") == "Wingdings" && IsSmiley(element.Value)
            select element;
    
        foreach (XElement element in smilies.ToList())
        {
            XElement textSmiley = new XElement(element.Name.Namespace + "Span",
                                               new XElement(element.Name.Namespace + "Run", GetTextSmiley(element.Value)));
            element.ReplaceWith(textSmiley);
        }
    
        using (MemoryStream memoryStreamChanged = new MemoryStream())
        {
            StreamWriter streamWriter = new StreamWriter(memoryStreamChanged);
            streamWriter.Write(root.ToString(SaveOptions.DisableFormatting));
            streamWriter.Flush();
            FlowDocument flowDocumentChanged = new FlowDocument();
            TextRange textRangeChanged =
                new TextRange(flowDocument.ContentStart, flowDocument.ContentEnd);
            textRangeChanged.Load(memoryStreamChanged, DataFormats.Xaml);
            return textRangeChanged.Text;
        }
    }
    
    private static string GetTextSmiley(string value)
    {
        switch (value)
        {
            case "J" :
                return ":)";
            case "K" :
                return ":|";
            case "L" :
                return ":(";
            default :
                throw new ArgumentException();
        }
    }
    
    private static bool IsSmiley(string value)
    {
        return value == "J" || value == "K" || value == "L";
    }