下载:https://pan.baidu.com/s/1NkRguBs9Bfm5NcTs7NcxFQ
在其他地方发布过,都是这里写的。
为Wpf方式,生成的气泡宽度高度较为精确。
适用任意字体以及字号,可设置图像字体、字号、行间距、字间距、阴影、气泡宽度等,在RichtextboxHelper.cs内查看。
生成的气泡宽度高度较为精确。
如有高度不一致问题,是因为文字高度超出了插入图像的高度,可对文字大小或图像进行调整。
注意:
green_left_mess.png、green_right_mess.png、white_left_mess.png、white_right_mess.png
4个文件设置为“嵌入的资源”。
本例子附带5种文字,均为外部调用,不用安装或加入资源文件。
附带消息框photoshop文件,除不能调整大小外,可以ps设置任意方向、透明度、颜色、阴影等在程序中调用。
主要是操作Richtextbox组件
RichtextboxHelper.cs
///
/// ** 文字高度 必须小于 插入的图像的高度,这里不做检测
/// * RichtextBox使用默认字体,如设定字体,修改替换的字符串
/// * Example:
/// RichtextboxHelper rtbHelper = new RichtextboxHelper();
/// // 可设置行间距、字间距、dpi、图像表示以及图像大小(宽度高度相同)
///
/// rtbHelper.Coordinates(rtbHelper.RtbToSubstitution(RichtextBox控件), 宽度, 字体, 字体大小); // 取得RichTextBox内容并转换
/// Grid grid = new Grid(); // 建立Grid
/// grid.SetValue(Canvas.LeftProperty,400.0); // 左边距
/// grid.SetValue(Canvas.TopProperty, 200.0); // 顶边距
/// rtbHelper.DrawText("图像资源文件所在的命名空间.图像路径.", grid,方向(左、右), 限定宽度, 字体, 字体大小, 颜色, 是否显示阴影,阴影模糊半径,阴影透明度);
/// 控件.Children.Add(grid); // 添加到窗体控件
///
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
public class RichtextboxHelper
{
public double objectWidth, objectHeight; // 结果图像的宽度、高度
public double Dpix { get; set; } = 96;
public double Dpiy { get; set; } = 96;
public double lineSpacing { get; set; } = 0; // 行间距
public double wordsSpacing { get; set; } = 0; // 字间距
public string flag { get; set; } = "▣"; // 图像标识
public int imagesize { get; set; } = 28; // 插入的图像大小
///
/// 屏蔽回车键
///
/// richtextbox控件
public void DisableEnterKey(RichTextBox rtb)
{
rtb.PreviewKeyDown += Rtb_PreviewKeyDown;
}
///
/// 按键事件
///
///
///
private void Rtb_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyStates == Keyboard.GetKeyStates(Key.Enter))
{
e.Handled = true;
}
}
///
/// richtextbox清除粘贴格式
///
/// richtextbox控件
public void ClearPasteformat(RichTextBox rtb)
{
CommandBinding PasteCommand = new CommandBinding();
PasteCommand.Command = ApplicationCommands.Paste;
PasteCommand.Executed += PasteCommand_Executed;
rtb.CommandBindings.Add(PasteCommand);
}
///
/// 清除粘贴格式
///
///
///
private void PasteCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
RichTextBox rtb = (RichTextBox)sender;
string paste = Clipboard.GetText();
paste = paste.Replace("\n", "").Replace("\t", "").Replace("\r", "").
Replace("" , "").
Replace("", "").
Replace("" , "").
Replace("" , "").
Replace("" , "").
Replace("", "");
Clipboard.Clear();
Clipboard.SetText(paste);
rtb.Paste();
e.Handled = true;
}
///
/// richtextbox添加图像
///
/// richtextbox控件
/// 图像地址
public void AddRtbImage(RichTextBox rtb, string imageUrl)
{
Image image = new Image()
{
Width = imagesize,
Height = imagesize,
UseLayoutRounding = true,
Source = new BitmapImage(new Uri(imageUrl, UriKind.RelativeOrAbsolute))
};
new InlineUIContainer(image, rtb.Selection.Start);
rtb.Focus();
/* // 光标移动
rtb.RaiseEvent(
new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, Key.Right)
{ RoutedEvent = UIElement.KeyDownEvent }
);
*/
}
///
/// 文字属性
///
private class CharacterAttribte
{
public string character; // 文字
public double characterX; // 文字位置
public int characterY; // 坐标 y
public double characterWidth; // 文字宽度
public double characterHeight; // 文字高度
public double offsetX; // 坐标位置 x
public CharacterAttribte(string s, double x, int y, double w, double h)
{
character = s;
characterX = x;
characterY = y;
characterWidth = w;
characterHeight = h;
offsetX = characterX - characterWidth;
}
}
private List<CharacterAttribte> characterXY = new List<CharacterAttribte>(); // 全部文字集合
private List<int> lineHasImage = new List<int>(); // 有图像的行
private List<double> lineWidth = new List<double>(); // 每行的宽度
private List<double> lineOffsety = new List<double>(); // 每行的y坐标
private double fontHeight = 0; // 字体高度
///
/// richtextbox内部图像
///
public class RtbImage
{
public Image image;
public RtbImage(Image img)
{
image = img;
}
}
public static List<RtbImage> rtbImages = new List<RtbImage>(); // richtextbox内部图像集合
///
/// 取得全部文字相关信息
///
/// 字符串
/// 限定的宽度
/// 字体
/// 字体大小
public void Coordinates(string content, double width, string ftype, int fsize)
{
int charaY = 0;
double charaX = 0, _length = 0;
for (int i = 0; i < content.Length; i++)
{
double[] _getsize = new double[2];
if (content.Substring(i, 1) == flag)
{
_length = imagesize;
lineHasImage.Add(charaY);
_getsize[0] = imagesize;
_getsize[1] = imagesize;
}
else
{
_getsize = ObtainCharSize(content.Substring(i, 1), ftype, fsize);
_length = _getsize[0];
}
if ((charaX + _length) > width)
{
lineWidth.Add(charaX);
charaX = _length;
charaY += 1;
}
else
{
charaX += _length;
}
characterXY.Add(new CharacterAttribte(content.Substring(i, 1), charaX, charaY, _getsize[0], _getsize[1]));
}
lineWidth.Add(charaX);
lineHasImage = new HashSet<int>(lineHasImage).ToList();
}
///
/// 清除记录的文字信息
///
private void ClearInfo()
{
characterXY.Clear();
lineHasImage.Clear();
lineWidth.Clear();
lineOffsety.Clear();
rtbImages.Clear();
}
///
/// 取得richtextbox全部图像
///
/// richtextbox控件
private static void ObtainRtbImages(RichTextBox rtb)
{
foreach (Block block in rtb.Document.Blocks)
{
if (block is Paragraph)
{
Paragraph paragraph = (Paragraph)block;
foreach (Inline inline in paragraph.Inlines)
{
if (inline is InlineUIContainer)
{
InlineUIContainer uiContainer = (InlineUIContainer)inline;
if (uiContainer.Child is Image)
{
rtbImages.Add(new RtbImage((Image)uiContainer.Child));
}
}
}
}
}
}
///
/// 转换richtextbox内容为替代字符串
///
///
///
public string RtbToSubstitution(RichTextBox rtb)
{
ObtainRtbImages(rtb);
string xaml = string.Empty;
TextRange textRange = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
using (MemoryStream ms = new MemoryStream())
{
textRange.Save(ms, DataFormats.Xaml);
ms.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(ms);
xaml = sr.ReadToEnd();
};
int begin = xaml.IndexOf("" ) + 11;
int end = xaml.LastIndexOf("");
return xaml.Substring(begin, end - begin).
Replace(" ", flag).
Replace("" , "\r").
Replace("" , "").
Replace("" , "").
Replace("" , "").
Replace("", "");
}
///
/// 取得文字的高度、宽度
///
/// 文字
/// 字体
/// 字体大小
///
private double[] ObtainCharSize(string content, string ftype, double fsize)
{
double[] size = new double[2];
FormattedText formattext = new FormattedText(content, CultureInfo.InvariantCulture, FlowDirection.LeftToRight, new Typeface(ftype), fsize, Brushes.Black);
size[0] = formattext.Width + wordsSpacing;
size[1] = formattext.Height;
fontHeight = formattext.Height;
return size;
}
///
/// richtextbox内容生成图像
///
/// 图像资源所在命名空间
/// Grid控件
/// 限定的宽度
/// 字体
/// 字体大小
/// 文字颜色
/// 内容是否有阴影
/// 阴影模糊半径
/// 阴影透明度
///
public void DrawText(
string name_space,
Grid control,
int type,
int fwidth,
string fnt, double fntsize, Brush fontColor,
bool shadow = false, double blur = 10, double opacity = 0.4)
{
double _imagewidth = lineWidth.Max() > fwidth ? fwidth : lineWidth.Max();
double _imageheight = 0;
int box_width, box_height;
double vx, vy, _sety = 0;
for (int i = 0; i < lineWidth.Count; i++)
{
lineOffsety.Add(_sety);
if (lineHasImage.Contains(i))
{
_sety += imagesize + lineSpacing;
_imageheight += imagesize + lineSpacing;
}
else
{
_sety += fontHeight + lineSpacing;
_imageheight += fontHeight + lineSpacing;
}
}
vx = type == 0 ? 32 : 22;
if (shadow)
{
_imageheight += blur;
_imagewidth += blur;
box_width = (int)Math.Ceiling(_imagewidth) - 35 < 1 ? 1 : (int)Math.Ceiling(_imagewidth) - 35;
box_height = (int)Math.Ceiling(_imageheight) - 35 < 1 ? 1 : (int)Math.Ceiling(_imageheight) - 35;
vy = 19.0;
}
else
{
box_width = (int)Math.Ceiling(_imagewidth) - 35 < 1 ? 1 : (int)Math.Ceiling(_imagewidth) - 35 + (int)Math.Ceiling(blur);
box_height = (int)Math.Ceiling(_imageheight) - 35 < 1 ? 1 : (int)Math.Ceiling(_imageheight) - 35 + (int)Math.Ceiling(blur);
vy = 20.0;
}
RenderTargetBitmap composeImage = new RenderTargetBitmap((int)Math.Ceiling(_imagewidth), (int)Math.Ceiling(_imageheight), Dpix, Dpiy, PixelFormats.Default);
DrawingVisual drawingVisual = new DrawingVisual();
int img_index = 0;
for (int i = 0; i < characterXY.Count; i++)
{
FormattedText formattext = new FormattedText(characterXY[i].character, CultureInfo.InvariantCulture, FlowDirection.LeftToRight, new Typeface(fnt), fntsize, fontColor);
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
if (shadow)
{
drawingVisual.Effect = new DropShadowEffect() { BlurRadius = blur, Opacity = opacity };
}
double ih = 0;
if (lineHasImage.Contains(characterXY[i].characterY))
{
ih = (imagesize - fontHeight) / 2;
}
double offsetY = lineOffsety[characterXY[i].characterY] + ih;
if (characterXY[i].character == flag)
{
drawingContext.DrawImage(rtbImages[img_index].image.Source, new Rect(characterXY[i].offsetX, offsetY - ih, imagesize, imagesize));
img_index += 1;
}
else
{
drawingContext.DrawText(formattext, new Point(characterXY[i].offsetX, offsetY));
}
}
composeImage.Render(drawingVisual);
}
BitmapSource box = DrawMessage(name_space, box_width, box_height, type);
Image imageBox = new Image()
{
Source = box,
};
imageBox.SetValue(Canvas.LeftProperty,0.0);
imageBox.SetValue(Canvas.TopProperty, 0.0);
Image imageText = new Image()
{
Source = composeImage,
};
imageText.SetValue(Canvas.LeftProperty, vx);
imageText.SetValue(Canvas.TopProperty, vy);
Canvas canvas = new Canvas();
canvas.Children.Add(imageBox);
canvas.Children.Add(imageText);
control.Children.Add(canvas);
ClearInfo();
objectWidth = box.Width;
objectHeight = box.Height;
}
///
/// 绘制对话框
///
/// 图像资源文件命名空间.路径.
/// 宽度
/// 高度
/// 0-左方向,1-右方向
///
private BitmapImage DrawMessage(string name_space, int _width, int _height, int type)
{
System.Drawing.Rectangle[,] rect = new System.Drawing.Rectangle[2, 9] {
{ new System.Drawing.Rectangle(0, 0, 35, 40), new System.Drawing.Rectangle(35, 0, 145, 40), new System.Drawing.Rectangle(180, 0, 43, 40),
new System.Drawing.Rectangle(0, 66, 35, 22),new System.Drawing.Rectangle(35, 66, 145, 22),new System.Drawing.Rectangle(180, 66, 43, 22),
new System.Drawing.Rectangle(0, 40, 35, 26),new System.Drawing.Rectangle(35, 40, 145, 26) ,new System.Drawing.Rectangle(180, 40, 43, 26)
},
{ new System.Drawing.Rectangle(0, 0, 43, 40), new System.Drawing.Rectangle(43, 0, 145, 40), new System.Drawing.Rectangle(188, 0, 35, 40),
new System.Drawing.Rectangle(0, 66, 43, 22), new System.Drawing.Rectangle(43, 66, 145, 22), new System.Drawing.Rectangle(188, 66, 35, 22),
new System.Drawing.Rectangle(0, 40, 43, 26), new System.Drawing.Rectangle(43, 40, 145, 26),new System.Drawing.Rectangle(188, 40, 35, 26),
}
};
System.Drawing.Bitmap bmp;
if (type == 1)
{
Stream strm = GetType().Assembly.GetManifestResourceStream(name_space + "green_right_mess.png");
bmp = System.Drawing.Image.FromStream(strm) as System.Drawing.Bitmap;
}
else
{
Stream strm = GetType().Assembly.GetManifestResourceStream(name_space + "green_left_mess.png");
bmp = System.Drawing.Image.FromStream(strm) as System.Drawing.Bitmap;
}
System.Drawing.Bitmap TopLeft = bmp.Clone(rect[type, 0], System.Drawing.Imaging.PixelFormat.DontCare);
System.Drawing.Bitmap MidTop = bmp.Clone(rect[type, 1], System.Drawing.Imaging.PixelFormat.DontCare);
System.Drawing.Bitmap TopRight = bmp.Clone(rect[type, 2], System.Drawing.Imaging.PixelFormat.DontCare);
MidTop = ResetImageSize(MidTop, _width, MidTop.Height) as System.Drawing.Bitmap;
System.Drawing.Bitmap BottomLeft = bmp.Clone(rect[type, 3], System.Drawing.Imaging.PixelFormat.DontCare);
System.Drawing.Bitmap MidBottom = bmp.Clone(rect[type, 4], System.Drawing.Imaging.PixelFormat.DontCare);
System.Drawing.Bitmap BottomRight = bmp.Clone(rect[type, 5], System.Drawing.Imaging.PixelFormat.DontCare);
MidBottom = ResetImageSize(MidBottom, _width, MidBottom.Height) as System.Drawing.Bitmap;
System.Drawing.Bitmap CentralLeft = bmp.Clone(rect[type, 6], System.Drawing.Imaging.PixelFormat.DontCare);
System.Drawing.Bitmap MidCentral = bmp.Clone(rect[type, 7], System.Drawing.Imaging.PixelFormat.DontCare);
System.Drawing.Bitmap CentralRight = bmp.Clone(rect[type, 8], System.Drawing.Imaging.PixelFormat.DontCare);
CentralLeft = ResetImageSize(CentralLeft, CentralLeft.Width, _height) as System.Drawing.Bitmap;
MidCentral = ResetImageSize(MidCentral, MidCentral.Width, _height) as System.Drawing.Bitmap;
MidCentral = ResetImageSize(MidCentral, _width, _height) as System.Drawing.Bitmap;
CentralRight = ResetImageSize(CentralRight, CentralRight.Width, _height) as System.Drawing.Bitmap;
System.Drawing.Bitmap bmp_block = new System.Drawing.Bitmap(_width + 78, _height + 66);
System.Drawing.Graphics gblock = System.Drawing.Graphics.FromImage(bmp_block);
gblock.DrawImage(TopLeft, 0, 0, TopLeft.Width, TopLeft.Height);
gblock.DrawImage(MidTop, TopLeft.Width, 0, MidTop.Width, MidTop.Height);
gblock.DrawImage(TopRight, TopLeft.Width + MidTop.Width, 0, TopRight.Width, TopRight.Height);
gblock.DrawImage(CentralLeft, 0, TopLeft.Height, CentralLeft.Width, CentralLeft.Height);
gblock.DrawImage(MidCentral, CentralLeft.Width, MidTop.Height, MidCentral.Width, MidCentral.Height);
gblock.DrawImage(CentralRight, CentralLeft.Width + MidCentral.Width, TopRight.Height, CentralRight.Width, CentralRight.Height);
gblock.DrawImage(BottomLeft, 0, TopLeft.Height + CentralLeft.Height, BottomLeft.Width, BottomLeft.Height);
gblock.DrawImage(MidBottom, BottomLeft.Width, TopLeft.Height + CentralLeft.Height, MidBottom.Width, MidBottom.Height);
gblock.DrawImage(BottomRight, BottomLeft.Width + MidBottom.Width, TopLeft.Height + CentralLeft.Height, BottomRight.Width, BottomRight.Height);
return BitmapToImageSource(bmp_block);
}
private static bool ImageCallback()
{
return false;
}
///
/// 图像缩放
///
/// 图像
/// 宽度
/// 高度
///
private System.Drawing.Image ResetImageSize(System.Drawing.Image AtImage, int ImageWidth, int ImageHeight)
{
if (AtImage == null) return null;
System.Drawing.Image.GetThumbnailImageAbort imgCallback = new System.Drawing.Image.GetThumbnailImageAbort(ImageCallback);
System.Drawing.Image Img = null;
Img = AtImage.GetThumbnailImage(ImageWidth, ImageHeight, imgCallback, IntPtr.Zero);
return Img;
}
///
/// 转换bitmap 为 BitmapImage
///
/// bitmap位图
///
public BitmapImage BitmapToImageSource(System.Drawing.Bitmap bitmap)
{
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
memory.Position = 0;
BitmapImage bitmapimage = new BitmapImage();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();
return bitmapimage;
}
}
}