程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WPF 微信 MVVM 【續】發送部分QQ表情,wpfmvvm

WPF 微信 MVVM 【續】發送部分QQ表情,wpfmvvm

編輯:關於.NET

WPF 微信 MVVM 【續】發送部分QQ表情,wpfmvvm


今天主要記錄的就是發送QQ表情, WPF 微信 MVVM裡寫了,後期為了發送QQ表情,需要把TextBox替換為RichTextBox,接下來就說說替換的過程。

一、支持Binding的RichTextBox

RichTextBox雖然支持文字,圖片,鏈接,但是,原生的它不支持Binding,這個對於MVVM是很不方便的,因此,需要給RichTextBox設置一個依賴屬性Document,來讓它支持綁定,這樣才能繼續下一步。

public class BindableRichTextBox : RichTextBox
    {
        public new FlowDocument Document
        {
            get { return (FlowDocument)GetValue(DocumentProperty); }
            set { SetValue(DocumentProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Document.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DocumentProperty =
            DependencyProperty.Register("Document", typeof(FlowDocument), typeof(BindableRichTextBox), new FrameworkPropertyMetadata(null,new PropertyChangedCallback(OnDucumentChanged)));

        private static void OnDucumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RichTextBox rtb = (RichTextBox)d;
            rtb.Document = (FlowDocument)e.NewValue;
        }
    }
BindableRichTextBox

二、微信表情列表

做列表的方法寫在了Emoji選項列表這個博客裡,不過因為是針對微信來做,所以,還是修改了一部分。

首先,右鍵查看微信網頁版的源文件,會看到它的表情列表大概是這個樣子的代碼,從裡面獲取title和class裡的內容,做成一個XML文件

然後,去網上找QQ的表情壓縮包,這個不是難事,然後根據class進行命名,最後使用Emoji選項列表裡的方法就可以做成列表了,看下效果圖

三、String轉FlowDocument、FlowDocument轉String

網頁版微信,在F12下,發送一條消息,可以看到發送的報文是“文字+[表情內容]”(指QQ的表情,Emoji現在沒看到規律),因為,在轉換的時候,也就有了目標

1、FlowDocument轉換String

我們在點擊發送按鈕之前,是將發送框裡的FlowDocument轉換成String發送出去的。

轉換過程是,循環FlowDocument裡面的Blocks(Paragraph都放在Blocks裡面),然後循環Paragraph裡的Inlines,判別裡面的內容是InlineUIContainer(Image)還是Run(Text)

如果是圖片的話,則從Dictionary裡取得Key,放到要發送的報文裡,如果是文字的話,就直接放就可以了

private string GetSendMessage(FlowDocument fld)
        {
            if (fld == null)
            {
                return string.Empty;
            }
            string resutStr = string.Empty;
            foreach (var root in fld.Blocks)
            {
                foreach (var item in ((Paragraph)root).Inlines)
                {
                    //如果是Emoji則進行轉換
                    if (item is InlineUIContainer)
                    {
                        System.Windows.Controls.Image img = (System.Windows.Controls.Image)((InlineUIContainer)item).Child;
                        resutStr += GetEmojiName(img.Source.ToString());
                    }
                    //如果是文本,則直接賦值
                    if (item is Run)
                    {
                        resutStr += ((Run)item).Text;
                    }
                }
            }
            return resutStr;
        }
FlowDocument轉String

2、String轉FlowDocument

接收消息的是,拿到的是String類型,但是顯示的時候要顯示成FlowDocument。

因為我們知道了消息的格式是XXXX[**]這種,因此,就選用正則表達式進行截取就可以了。

首先,判斷字符串的第一位是不是“[”,如果是的話,則截取[]裡面的內容,轉換為Image,然後將[**]從接收到的字符串上移除掉;

如果不是的話,則用正則表達式取得"["前面的值,作為Text,然後,將取到的值從接收到的字符串上移除掉,整個過程進行遞歸,直到字符串的長度變為0,跳出,將得到的內容最後添加到FlowDocument裡

private void StrToFlDoc(string str,FlowDocument fld,Paragraph par)
        {
            //當遞歸結束以後,也就是長度為0的時候,就跳出
            if (str.Length <= 0)
            {
                fld.Blocks.Add(par);
                return;
            }
            //如果字符串裡不存在[時,則直接添加內容
            if (!str.Contains('['))
            {
                par.Inlines.Add(new Run(str));
                str = str.Remove(0, str.Length);
                StrToFlDoc(str,fld, par);
            }
            else
            {
                //設置字符串長度
                int strLength = str.Length;
                //首先判斷第一位是不是[,如果是,則證明是表情,用正則獲取表情,然後將字符串長度進行移除,遞歸
                if (str[0].Equals('['))
                {
                    par.Inlines.Add(new InlineUIContainer(new System.Windows.Controls.Image { Width = 20, Height = 20, Source = ContantClass.EmojiCode[GetEmojiNameByRegex(str)] }));
                    str = str.Remove(0, GetEmojiNameByRegex(str).Length);
                    StrToFlDoc(str,fld, par);
                }
                else
                {//如果第一位不是[的話,則是字符串,直接添加進去
                    par.Inlines.Add(new Run(GetTextByRegex(str)));
                    str = str.Remove(0, GetTextByRegex(str).Length);
                    StrToFlDoc(str,fld, par);
                }
            }
        }
String轉FlowDocument

看下最終的效果圖

四、總結

在把Textbox替換為RichTextBox過程中,遇到了不少阻礙,不像剛開始想的那麼簡單。

比如,點選表情添加到RichTextbox中時,發現有的時候光標並不在當前添加完的表情後面,而是在前面,或者是隔了一個跳躍,研究了大半天,在網上找到了解決辦法。

var container=new InlineUIContainer(new Image { Source = EmojiTabControlUC.SelectEmoji.Value, Height = 20, Width = 20 }, rtb.CaretPosition);
rtb.CaretPosition = container.ElementEnd;

獲取當前添加圖片的位置,然後將位置重新定義為它之後。

還有,就是大家看到我的聊天框裡的RichTextBox的長度是對等的,原來用TextBox時,會根據內容的長度進行變化,然後有一個最大長度,但是,我現在始終也沒有找到如何讓長度Auto的方法,請大神們告知如何搞定。

 

代碼的話,繼續是GitHub,地址的話,在WPF 微信 MVVM帖子裡有,這裡就不寫了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved