创建一个自定义用户控件,拖入一个label:lblWords,和一个richTextBox:txtWords

代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms; namespace WinBubble
{
public partial class ucBubble : UserControl
{
#region 属性字段
private Color gdiBackColor;//GDI+绘制的背景色-->如果和txt背景色不一致,在文本框和GDI+背景色之间会形成一个边框效果
private Color txtBackColor;//多行文本框的背景色
private Color foreColor;//多行文本框的前景色
private Font font;//字体
private string words;//文本
private string direction;//气泡箭头方向
private int rowsCount = ;//多行文本框的行数-->估算值 private const int X = ;//气泡箭头三角形的高
private const int Round = ;//圆角半径
private const int M = ;//文本框和uc边框的距离 public string CurrentText { get { return txtWords.Text.Replace("\n", ""); } }//文本框的内容
public string SelectedText { get { return txtWords.SelectedText; } }//选中的内容
#endregion #region 接口
public ucBubble(int width, Color gdiBackColor, Color txtBackColor, Color foreColor, int fontSize, string fontFamily, string words, string direction)
{
InitializeComponent(); this.Width = width;
this.gdiBackColor = gdiBackColor;
this.txtBackColor = txtBackColor;
this.foreColor = foreColor;
this.font = new Font(new FontFamily(string.IsNullOrEmpty(fontFamily) ? "微软雅黑" : fontFamily), fontSize);
this.words = words;
this.direction = direction == "right" ? "right" : "left"; //内容文本框
txtWords.BorderStyle = BorderStyle.None;
txtWords.ScrollBars = RichTextBoxScrollBars.None;
txtWords.ImeMode = ImeMode.OnHalf;
txtWords.BackColor = txtBackColor;
txtWords.ForeColor = foreColor;
txtWords.Text = words;
txtWords.Font = font; //lblWords标签的作用是用来判断文本框内容是不是多行的,因为单行内容需要根据宽度进行定位。如果是单行内容,就让文本框的宽度和标签的宽度相等
lblWords.Visible = false;
lblWords.Location = new Point(X + M, );
lblWords.Text = "";
lblWords.Font = font; //事件
this.Paint += new PaintEventHandler(ucBubble_Paint);
this.MouseWheel += new MouseEventHandler(ucBubble_MouseWheel);
this.MouseClick += new MouseEventHandler(ucBubble_MouseClick);
this.DoubleClick += new EventHandler(ucBubble_DoubleClick); txtWords.MouseWheel += new MouseEventHandler(ucBubble_MouseWheel);
txtWords.MouseClick += new MouseEventHandler(ucBubble_MouseClick);
txtWords.DoubleClick += new EventHandler(ucBubble_DoubleClick);
txtWords.KeyPress += new KeyPressEventHandler(txtWords_KeyPress); rowsCount = GetRowsCount();
ControlRichTextBox();
SelectWords(, );
} //从文本中找到匹配的内容,然后改变前景色或者背景色,返回值是txtWords中匹配的个数。foreColorIndex和backColorIndex用来控制只改其中指定的一个匹配内容的颜色。
public int SelectSomething(string something, Color[] changeForeColor = null, int foreColorIndex = , Color[] changeBackColor = null, int backColorIndex = )
{
int count = ;//匹配个数
int start = txtWords.Find(something, , RichTextBoxFinds.None);//匹配内容开始索引 if (start >= )//存在匹配内容
{
count++;
txtWords.SelectionStart = start;
txtWords.SelectionLength = something.Length;
if (changeForeColor != null && changeForeColor.Length > )
{
if (foreColorIndex <= || (foreColorIndex > && foreColorIndex == count))
{
txtWords.SelectionColor = changeForeColor[];//改变前景色
}
}
if (changeBackColor != null && changeBackColor.Length > )
{
if (backColorIndex <= || (backColorIndex > && backColorIndex == count))
{
txtWords.SelectionBackColor = changeBackColor[];//改变背景色
}
} //匹配下一个
while (txtWords.Text.Length > start + something.Length)
{
start = txtWords.Find(something, start + something.Length, RichTextBoxFinds.None);
if (start >= )
{
count++;
txtWords.SelectionStart = start;
txtWords.SelectionLength = something.Length; if (changeForeColor != null && changeForeColor.Length > )
{
if (foreColorIndex <= || (foreColorIndex > && foreColorIndex == count))
{
txtWords.SelectionColor = changeForeColor[];//改变前景色
}
}
if (changeBackColor != null && changeBackColor.Length > )
{
if (backColorIndex <= || (backColorIndex > && backColorIndex == count))
{
txtWords.SelectionBackColor = changeBackColor[];//改变背景色
}
}
}
else
break;
}
} //返回匹配个数
return count;
} //还原富文本框的颜色
public void ClearSomething()
{
txtWords.SelectionStart = ;
txtWords.SelectionLength = txtWords.Text.Length;
txtWords.SelectionColor = foreColor;
txtWords.SelectionBackColor = txtBackColor;
} //选中内容
public void SelectWords(int start, int length)
{
txtWords.Select(start, length);
}
#endregion #region 方法
//获取文本内容占用的行数
private int GetRowsCount()
{
int count = ;
char[] chars = words.ToCharArray();
for (int i = ; i < chars.Length; i++)
{
lblWords.Text = lblWords.Text + chars[i];
if (X + M + lblWords.Width + M > this.Width)
{
lblWords.Text = "";
i--;
count++;
}
}
return count;
} //控制文本框的位置和大小
private void ControlRichTextBox()
{
if (rowsCount > )
txtWords.Width = this.Width - X - M - M; //文本框的宽度=控件宽度-箭头高-左侧留白-右侧留白
else
txtWords.Width = lblWords.Width; txtWords.Height = rowsCount * font.Height;
//调整误差
if (font.Size == )
txtWords.Height += rowsCount * ;
else if (font.Size == )
txtWords.Height += rowsCount * ;
else if (font.Size == )
txtWords.Height += rowsCount * ;
else if (font.Size == )
txtWords.Height += rowsCount * ;
else if (font.Size == )
txtWords.Height += rowsCount * ;
else
txtWords.Height += rowsCount * (font.Height / ); //整个uc的高度
this.Height = txtWords.Height + M + M; //位置
if (this.direction == "left")
{
txtWords.Location = new Point(X + M, M);
}
else
{
if (rowsCount > )
txtWords.Location = new Point(M, M);
else
txtWords.Location = new Point(this.Width - lblWords.Width - X - M, M);
}
} //绘制箭头和圆角:气泡箭头在左侧
private void DrawBubbleLeft(Graphics graphics, Color c)
{
SolidBrush brush = new SolidBrush(c);//定义画刷
int lblMax = X + M + lblWords.Width + M; if (rowsCount > )
{
//背景
Point[] points = new Point[]
{
//左上角
new Point(X,Round),
new Point(X+Round,),
//右上角
new Point(this.Width-Round,),
new Point(this.Width,Round),
//右下角
new Point(this.Width,this.Height-Round),
new Point(this.Width -Round,this.Height),
//左下角
new Point(X+Round ,this.Height),
new Point(X,this.Height-Round)
};
graphics.FillPolygon(brush, points); //绘制圆角
graphics.FillEllipse(brush, X, , Round * , Round * );//左上圆角
graphics.FillEllipse(brush, this.Width - Round * , , Round * , Round * );//右上圆角
graphics.FillEllipse(brush, this.Width - Round * , this.Height - Round * , Round * , Round * );//右下圆角
graphics.FillEllipse(brush, X, this.Height - Round * , Round * , Round * );//左下圆角 //三角形
Point[] points2 = new Point[]
{
new Point(X,),
new Point( ,),
new Point(X,)
};
graphics.FillPolygon(brush, points2);
}
else
{
//背景
Point[] points = new Point[]
{
//左上角
new Point(X,Round),
new Point(X+Round,),
//右上角
new Point(lblMax-Round,),
new Point(lblMax,Round),
//右下角
new Point(lblMax,this.Height-Round),
new Point(lblMax -Round,this.Height),
//左下角
new Point(X+Round ,this.Height),
new Point(X,this.Height-Round)
};
graphics.FillPolygon(brush, points); //绘制圆角
graphics.FillEllipse(brush, X, , Round * , Round * );//左上圆角
graphics.FillEllipse(brush, lblMax - Round * , , Round * , Round * );//右上圆角
graphics.FillEllipse(brush, lblMax - Round * , this.Height - Round * , Round * , Round * );//右下圆角
graphics.FillEllipse(brush, X, this.Height - Round * , Round * , Round * );//左下圆角 //三角形
Point[] points2 = new Point[]
{
new Point(X,),
new Point( ,),
new Point(X,)
};
graphics.FillPolygon(brush, points2);
}
} //绘制箭头和圆角:气泡箭头在右侧
private void DrawBubbleRight(Graphics graphics, Color c)
{
SolidBrush brush = new SolidBrush(c);//定义画刷
int lblMax = X + M + lblWords.Width + M; if (rowsCount > )
{
//背景
Point[] points = new Point[]
{
//左上角
new Point(,Round),
new Point(Round,),
//右上角
new Point(this.Width-X-Round,),
new Point(this.Width-X,Round),
//右下角
new Point(this.Width-X,this.Height-Round),
new Point(this.Width-X-Round,this.Height),
//左下角
new Point(Round ,this.Height),
new Point(,this.Height-Round)
};
graphics.FillPolygon(brush, points); //绘制圆角
graphics.FillEllipse(brush, , , Round * , Round * );//左上圆角
graphics.FillEllipse(brush, this.Width - X - Round * , , Round * , Round * );//右上圆角
graphics.FillEllipse(brush, this.Width - X - Round * , this.Height - Round * , Round * , Round * );//右下圆角
graphics.FillEllipse(brush, , this.Height - Round * , Round * , Round * );//左下圆角 //三角形
Point[] points2 = new Point[]
{
new Point(this.Width-X,),
new Point(this.Width,),
new Point(this.Width-X,)
};
graphics.FillPolygon(brush, points2);
}
else
{
//背景
Point[] points = new Point[]
{
//左上角
new Point(this.Width-lblMax,Round),
new Point(this.Width-lblMax+Round,),
//右上角
new Point(this.Width-X-Round,),
new Point(this.Width-X,Round),
//右下角
new Point(this.Width-X,this.Height-Round),
new Point(this.Width-X-Round,this.Height),
//左下角
new Point(this.Width-lblMax+Round ,this.Height),
new Point(this.Width-lblMax,this.Height-Round)
};
graphics.FillPolygon(brush, points); //绘制圆角
graphics.FillEllipse(brush, this.Width - lblMax, , Round * , Round * );//左上圆角
graphics.FillEllipse(brush, this.Width - X - Round * , , Round * , Round * );//右上圆角
graphics.FillEllipse(brush, this.Width - X - Round * , this.Height - Round * , Round * , Round * );//右下圆角
graphics.FillEllipse(brush, this.Width - lblMax, this.Height - Round * , Round * , Round * );//左下圆角 //三角形
Point[] points2 = new Point[]
{
new Point(this.Width-X,),
new Point(this.Width,),
new Point(this.Width-X,)
};
graphics.FillPolygon(brush, points2);
}
}
#endregion #region 事件
//绘制气泡事件
public void ucBubble_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = e.Graphics;
if (direction == "left")
DrawBubbleLeft(graphics, gdiBackColor);
else
DrawBubbleRight(graphics, gdiBackColor);
} //滚动事件
public event Action BubbleMouseWheel;
public void ucBubble_MouseWheel(object sender, MouseEventArgs e)
{
if (BubbleMouseWheel != null)
BubbleMouseWheel();
} //单击事件
public event Action BubbleClick;
public void ucBubble_MouseClick(object sender, MouseEventArgs e)
{
if (BubbleClick != null)
BubbleClick();
} //双击事件
public event Action BubbleDoubleClick;
public void ucBubble_DoubleClick(object sender, EventArgs e)
{
if (BubbleDoubleClick != null)
BubbleDoubleClick();
} //回车事件
public event Action BubbleKeyPress;
public void txtWords_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == )
{
e.Handled = true; if (BubbleKeyPress != null)
BubbleKeyPress();
}
}
#endregion
}
}

使用:

ucBubble uc1 = new ucBubble(, Color.Brown, Color.Red, Color.Black, , "微软雅黑", "Hello World!", "left");
uc1.Location = new Point(, );
this.Controls.Add(uc1); ucBubble uc2 = new ucBubble(, Color.Brown, Color.Green, Color.Black, , "微软雅黑", "Hello World!", "right");
uc2.Location = new Point(, );
this.Controls.Add(uc2); ucBubble uc3 = new ucBubble(, Color.Brown, Color.Red, Color.Black, , "微软雅黑", "Hello World!Hello World!Hello World!Hello World!Hello World!", "left");
uc3.Location = new Point(, );
this.Controls.Add(uc3); ucBubble uc4 = new ucBubble(, Color.Brown, Color.Green, Color.Black, , "微软雅黑", "Hello World!Hello World!Hello World!Hello World!", "right");
uc4.Location = new Point(, );
this.Controls.Add(uc4);

效果:

WindowsForm--Bubble User Control的更多相关文章

  1. Massively parallel supercomputer

    A novel massively parallel supercomputer of hundreds of teraOPS-scale includes node architectures ba ...

  2. Control Flow 如何处理 Error

    在Package的执行过程中,如果在Data Flow中出现Error,那么Data Flow component能够将错误行输出,只需要在组件的ErrorOutput中进行简单地配置,参考<D ...

  3. Tutorial: WPF User Control for AX2012

    原作者: https://community.dynamics.com/ax/b/goshoom/archive/2011/10/06/tutorial-wpf-user-control-for-ax ...

  4. wpf custom control

    最近在做WPF,记录一下自定义控件的制作过程,源码请点击:源码. 1.目标 实现一个如图所示的可增减的数字框: 2.先画Template 可以在Generic.xaml中画,也可以用MergedDic ...

  5. [译]Stairway to Integration Services Level 9 - Control Flow Task Errors

    介绍 在本文中,我们会实验 MaximumErrorCount和ForceExecutioResult 故障容差属性,并且还要学习Control Flow task errors, event han ...

  6. Writing a Reusable Custom Control in WPF

    In my previous post, I have already defined how you can inherit from an existing control and define ...

  7. 企业管理软件开发架构之七 Object Control设计与运用

    在做查询时,经常遇到一类需求.请看下面的SQL语句查询 SELECT * FROM Company WHERE CompanyCode='Kingston' AND Suspended='N' AND ...

  8. 文字处理控件TX Text Control的使用

    这几天一直在研究TX Text Control的使用,由于这方面的资料相对比较少,主要靠下载版本的案例代码进行研究,以及官方的一些博客案例进行学习,使用总结了一些心得,特将其总结出来,供大家分享学习. ...

  9. Sublime text 2/3 中 Package Control 的安装与使用方法

    Package Control 插件是一个方便 Sublime text 管理插件的插件,但因为 Sublime Text 3 更新了 Python 的函数,API不同了,导致基于 Python 开发 ...

  10. Java中的经典算法之冒泡排序(Bubble Sort)

    Java中的经典算法之冒泡排序(Bubble Sort) 神话丿小王子的博客主页 原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一 ...

随机推荐

  1. 黑马------synchronized详解

    黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA线程-synchronized详解 一.synchronized概述 1.线程间实现互斥,必须使用同一个监视器(一个对象 ...

  2. 黑马----JAVA异常

    黑马程序员:Java培训.Android培训.iOS培训..Net培训 黑马程序员--JAVA异常 一.JAVA异常有三种语句块:try语句块.catch语句块.finally语句块. 1.try语句 ...

  3. linux驱动的分离分层概念之LED

    bus_drv_dev模型:功能改写只需改dev硬件代码即可,drv不需改写. LED例子 下面用一个点亮LED的例子来说明这个分离的的例子: led_dev.c  定义这个平台设备的资源: stat ...

  4. Matlab代码优化--向量化

    前段时间改写老师的一个计算纳米细颗粒物的C语言程序,不过运行的效率实在是太低了,工作站跑都很吃劲,晚上看了冈萨雷斯的数字图像处理意外发现了问题所在.在将C语言的程序改写成Matlab程序的时候我还是保 ...

  5. CentOS7 监控进程网络流量工具安装

    服务器在做测试的时候,需要监控网络流量,用来了解在不同人数的时候服务器的网络使用量. 我们使用服务器环境是centos7,centos下通常使用iftop,或者nethogs来进行网络流量监控.这2个 ...

  6. Android---闪频页和倒计时

    android闪频的实现非常简单,使用Handler对象的postDelayed()方法就可以实现.在这个方法里传递一个Runnable对象和一个延迟的时间.该方法实现了一个延迟执行的效果,延迟的时间 ...

  7. include/asm/dma.h

    /* $Id: dma.h,v 1.7 1992/12/14 00:29:34 root Exp root $ * linux/include/asm/dma.h: Defines for using ...

  8. Spark 累加器

    由于spark是分布式的计算,所以使得每个task间不存在共享的变量,而为了实现共享变量spark实现了两种类型 - 累加器与广播变量, 对于其概念与理解可以参考:共享变量(广播变量和累加器).可能需 ...

  9. web服务器软件集成包问题

    今天下了wampserver,运行错误缺少dll,然后下载apprev也是,最后下了个wampserver 32位了终于没问题了.

  10. Linear Algebra lecture10 note

    Four fundamental subspaces( for matrix A)   if A is m by n matrix: Column space  C(A) in Rm (列空间在m维实 ...