导航
  • 主页
  • C#综合技术
  • C#互联网桌面应用
  • AppLauncher
  • WinForm
  • WPF
  • 问答

【WPF】RichTextBox复制表情图片,没法获取挂图片的源文件地址

小眼聚光~ 正在学习中的码农  2019-03-06 07:29:36
项目中有个小问题,
用RichTextBox作为聊天输入框,当然聊天气泡也是用的是RichTextBox。
一切都还算正常,包括显示方式都参考网上资料实现了。。。直到。。。

在项目后期突然想起来,由于我昨的这个聊天系统包含表情符号,使用converter去筛选所有字符包含表情符号的,并且替换成对应的表情图片。

但是RichTextBox的复制粘贴,在对文本字符操作都很OK,对于图片的处理就比较。。




在对RichTextBox进行内容复制的时候,如果连带表情图片也一起复制进去,flowerdocument格式会变得超出我的预期(我在解析字符的时候统一使用run和uielement逐个添加到flowdocument中,但是复制出来的带表情的flowerdocument格式并不是这样的)

并且复制的图片也不是我绑定的图片的路径,根据网上的资料,好像是WPF自动暂存了这个图片,但是我这个图片作为表情图片, 肯定需要获取到图片路径,再去对应表情字符,再去转发给手机端,电脑端。


```
<FlowDocument LineHeight="1" MaxPageWidth="460" PagePadding="5,0,5,0" AllowDrop="True" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><Paragraph><Image Width="20" Height="20"><Image.Source><BitmapImage BaseUri="pack://payload:,,wpf1,/Xaml/Document.xaml" UriSource="./Image1.png" CacheOption="OnLoad" /></Image.Source></Image><Image Width="20" Height="20"><Image.Source><BitmapImage BaseUri="pack://payload:,,wpf1,/Xaml/Document.xaml" UriSource="./Image2.png" CacheOption="OnLoad" /></Image.Source></Image></Paragraph></FlowDocument>
```
如图,本来一张具有完整路径的表情图片,现在变成这样


网上的群友们的建议用RTF格式,但是我对RTF暂时毫无接触,请问是否还有别的办法应对这种RichTextBox复制图片的问题,我只想能够获取到每个图片的对应的原始复制的图片的地址



PS:这问题想了好几天没想到好办法解决,网上相关资料并不多,大多都是说把图片重新保存一份,但我要获取的是复制的图片的路径,好去获取对应的表情字符。
PS2:不知道自定义控件能不能解决这个问题,但是刚学这个,自定义控件的实现目前还不太懂。

请各位大佬给一些想法提供一些思路。有经验的最好能聊聊你们的聊天表情如何在客户端上实现的。
...全文
129 点赞 收藏 7
写回复
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
小眼聚光~ 2019-03-06
加分啦,只想请教一个思路就行~我会一一进行测试验证滴~
回复
小眼聚光~ 2019-03-06
引用 4 楼 desperaso 的回复:
补充:那个public class ImageStruct 干别的用的,可以删掉



非常感谢您花时间指导我,非常感谢,太谢谢啦~

然后,您给我的这个自定义控件是winform的,我用的wpf,倒是没试过能不能结合起来用,我先去尝试着理解一下您这个代码哈~
回复
desperaso 2019-03-06
补充:那个public class ImageStruct 干别的用的,可以删掉
回复
desperaso 2019-03-06

using System;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Collections.Generic;

public class RichTextEx : RichTextBox
{
public RichTextEx()
{
}

protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0007)
{
foreach (Control _SubControl in base.Controls)
{
_SubControl.Tag = "1";
}

GetRichTextObjRectangle();

for (int i = 0; i != base.Controls.Count; i++)
{
if (base.Controls[i].Tag.ToString() == "1")
{
base.Controls.RemoveAt(i);
i--;
}
}
}
base.WndProc(ref m);
}

public class ImageStruct
{
public Point Img_Point;
public int Img_Location;
public Bitmap Img;

public ImageStruct(Point _point, int _location, Bitmap _img)
{
Img_Point = _point;
Img_Location = _location;
Img = _img;
}
}
public List<ImageStruct> ImageList = new List<ImageStruct>();


public class ContentStruct
{
public Point Content_Point;
public string Content_Text;

public ContentStruct(Point _point, string _text)
{
Content_Point = _point;
Content_Text = _text;
}
}
public List<ContentStruct> ContentList = new List<ContentStruct>();

private Bitmap _bmp = new Bitmap(96, 96);

/*
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
*/

public void AddFile(string p_FileFullPath)
{
byte[] _FileBytes = File.ReadAllBytes(p_FileFullPath);
Image _Image = Image.FromStream(new MemoryStream(_FileBytes));
string _Guid = BitConverter.ToString(Guid.NewGuid().ToByteArray()).Replace("-", "");
StringBuilder _RtfText = new StringBuilder(@"{\rtf1\ansi\ansicpg936\deff0\deflang1033\deflangfe2052{\fonttbl{\f0\fnil\fcharset134 \'cb\'ce\'cc\'e5;}}\uc1\pard\lang2052\f0\fs18{\object\objemb{\*\objclass Paint.Picture}");
int _Width = _Image.Width * 15;
int _Height = _Image.Height * 15;
_RtfText.Append(@"\objw" + _Width.ToString() + @"\objh" + _Height.ToString());
_RtfText.AppendLine(@"{\*\objdata");
_RtfText.AppendLine(@"010500000200000007000000504272757368000000000000000000" + BitConverter.ToString(BitConverter.GetBytes(_FileBytes.Length + 20)).Replace("-", ""));
_RtfText.Append("7A676B65" + _Guid);
_RtfText.AppendLine(BitConverter.ToString(_FileBytes).Replace("-", ""));
_RtfText.AppendLine(@"0105000000000000}{\result{\pict\wmetafile0}}}}");
base.SelectedRtf = _RtfText.ToString();
}

private void PointFile(string p_Rtf, Point p_StarPoint, int p_Width, int p_Height)
{
int _Index = p_Rtf.IndexOf(@"{\*\objdata");
if (_Index == -1) return;
_Index += 80;
string _LengthText = p_Rtf.Substring(_Index, 8);

int _Length = BitConverter.ToInt32(new byte[] { Convert.ToByte(_LengthText.Substring(0, 2), 16), Convert.ToByte(_LengthText.Substring(2, 2), 16), Convert.ToByte(_LengthText.Substring(4, 2), 16), Convert.ToByte(_LengthText.Substring(6, 2), 16) }, 0);
_Index += 10;

string _Head = p_Rtf.Substring(_Index, 8);
if (_Head.ToUpper() != "7A676B65") return;
_Index += 8;

string _Guid = p_Rtf.Substring(_Index, 32);

Control _Controls = base.Controls[_Guid];
if (_Controls == null)
{
PictureBox _PictureBox = new PictureBox();
_PictureBox.Name = _Guid;
_PictureBox.Tag = "0";
_PictureBox.Location = p_StarPoint;
_PictureBox.Size = new Size(p_Width, p_Height);

_Index += 32;
_Length -= 20;

_PictureBox.Image = Image.FromStream(LoadMemoryStream(p_Rtf, ref _Index, _Length));

_bmp = _PictureBox.Image as Bitmap;
base.Controls.Add(_PictureBox);
}
else
{
_Controls.Location = p_StarPoint;
_Controls.Size = new Size(p_Width, p_Height);
_Controls.Tag = "0";
}
}

private MemoryStream LoadMemoryStream(string p_Text, ref int p_Index, int p_Count)
{
MemoryStream _File = new MemoryStream();
char[] _Text = p_Text.ToCharArray();
for (int i = 0; i != p_Count; i++)
{
if (_Text[p_Index] == '\r' && _Text[p_Index + 1] == '\n')
{
i--;
}
else
{
_File.WriteByte(Convert.ToByte(_Text[p_Index].ToString() + _Text[p_Index + 1].ToString(), 16));
}
p_Index += 2;
}
return _File;
}

private void GetRichTextObjRectangle()
{
ImageList.Clear();
ContentList.Clear();

RichTextBox _RichText = new RichTextBox();
_RichText.Rtf = base.Rtf;
int _Count = base.Text.Length;

for (int i = 0; i != _Count; i++)
{
if (base.Text[i] == ' ')
{
_RichText.Select(i, 1);

if (_RichText.SelectionType.ToString() == "Object")
{
Point _StarPoint = base.GetPositionFromCharIndex(i);

System.Text.RegularExpressions.Regex _RegexWidth = new System.Text.RegularExpressions.Regex(@"(?<=\\objw)[^\\]+");
System.Text.RegularExpressions.Regex _RegexHeight = new System.Text.RegularExpressions.Regex(@"(?<=\\objh)[^{]+");

int _Width = 0;
int _Height = 0;

if (int.TryParse(_RegexWidth.Match(_RichText.SelectedRtf).Value, out _Width) && int.TryParse(_RegexHeight.Match(_RichText.SelectedRtf).Value, out _Height))
{
_Width = _Width / 15;
_Height = _Height / 15;
PointFile(_RichText.SelectedRtf, _StarPoint, _Width, _Height);

ImageList.Add(new ImageStruct(_StarPoint, i, _bmp));
}
}
else
{
Point _StarPoint = base.GetPositionFromCharIndex(i);
ContentList.Add(new ContentStruct(_StarPoint, _RichText.SelectedText));
}
}
else
{
_RichText.Select(i, 1);
Point _StarPoint = base.GetPositionFromCharIndex(i);
ContentList.Add(new ContentStruct(_StarPoint, _RichText.SelectedText));
}
}

_RichText.Dispose();
}

public void updata()
{
foreach (Control _SubControl in base.Controls)
{
_SubControl.Tag = "1";
}

GetRichTextObjRectangle();

for (int i = 0; i != base.Controls.Count; i++)
{
if (base.Controls[i].Tag.ToString() == "1")
{
base.Controls.RemoveAt(i);
i--;
}
}

}
}



// 添加一副图像
private void button2_Click(object sender, EventArgs e)
{
Rich.AddFile("face.png");
}


可以gif动画图。注意下if (m.Msg == 0x0007),可以改为别的消息来刷新,这里凑合着用焦点。
回复
小眼聚光~ 2019-03-06
不好意思,我截图有点没水准,上面的聊天我瞎打字测试玩的,

来几位大佬指点指点呢~

或者收徒也行呢
回复
小眼聚光~ 2019-03-06
顶起来呢,今天大神们都公司放假了呀
回复
小眼聚光~ 2019-03-06
少了一张图片,是后台查看复制到富文本框中的内容(已经转换成xml)
回复
发动态
发帖子
C#
创建于2007-09-28

10.4w+

社区成员

.NET技术 C#
申请成为版主
社区公告

全世界最好的语言,没有之一.