我有以下代码正在运行,并注释掉了绘制到控件上的文本,因为我开始将其用作仅图形控件。接下来,我已将控件切换为
RichTextBox
而不是 Control
,这样我就可以拥有它附带的所有好处,例如可点击的超链接、可选择的文本等。
我面临的问题是,可以选择文本,甚至可以复制文本,但它是不可见的,并且也没有准确定位在我想要的位置(取消注释
Messages.OnPaint()
方法中的文本打印行,看看我希望如何要出现的文字)
问题的漂亮图片
我正在努力实现的目标的漂亮图片
带有未注释的文本打印代码的漂亮图片
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
public class MessageControl : ScrollableControl {
public List<Message> Messages { get; private set; }
private Color _LeftBubbleColor=Color.FromArgb(217,217,217);
private Color _RightBubbleColor=Color.FromArgb(192,206,215);
private Color _LeftBubbleTextColor=Color.FromArgb(52,52,52);
private Color _RightBubbleTextColor=Color.FromArgb( 52, 52, 52 );
private bool _DrawArrow=true;
private int _BubbleIndent=40;
private int _BubbleSpacing=10;
private int _TruncateHistory=0;
public enum BubblePositionEnum { Left, Right }
public Color LeftBubbleColor { get { return _LeftBubbleColor; } set {_LeftBubbleColor = value; } }
public Color RightBubbleColor { get { return _RightBubbleColor; } set { _RightBubbleColor=value; } }
public Color LeftBubbleTextColor { get { return _LeftBubbleTextColor; } set { _LeftBubbleTextColor=value; } }
public Color RightBubbleTextColor { get { return _RightBubbleTextColor; } set { _RightBubbleTextColor=value; } }
public int BubbleIndent { get { return _BubbleIndent; } set { _BubbleIndent = value; } }
public int BubbleSpacing { get { return _BubbleSpacing; } set { _BubbleSpacing=value; } }
public bool DrawArrow { get { return _DrawArrow; } set { _DrawArrow = value; } }
public int TruncatHistory { get { return _TruncateHistory; } set { _TruncateHistory = value; } }
public MessageControl() {
Messages = new List<Message>();
SetStyle( ControlStyles.AllPaintingInWmPaint|ControlStyles.OptimizedDoubleBuffer|ControlStyles.ResizeRedraw|ControlStyles.SupportsTransparentBackColor|ControlStyles.UserPaint, true );
DoubleBuffered=true;
BackColor=Color.Orange;
Anchor=AnchorStyles.Top|AnchorStyles.Left|AnchorStyles.Right|AnchorStyles.Bottom;
AutoScroll=true;
}
public void Remove( Message message ) {
this.Invalidate();
Messages.Remove( message );
RedrawControls();
}
public void Remove( Message[] messages ) {
foreach ( Message m in messages ) {
Messages.Remove( m );
}
RedrawControls();
this.Invalidate();
}
public void Add( string Message, BubblePositionEnum Position ) {
if ( Messages.Count>0 ) {
Message m = Messages[Messages.Count-1];
if ( m.BubblePosition==Position ) {
Message=m.Text+"\n"+Message;
Remove(m);
}
}
Message b = new Message(Position);
if ( Messages.Count>0 ) {
b.Top=Messages[Messages.Count-1].Top+Messages[Messages.Count-1].Height+_BubbleSpacing;
} else {
b.Top=_BubbleSpacing;
}
b.Text = Message;
b.DrawBubbleArrow=_DrawArrow;
if ( VerticalScroll.Visible ) {
b.Width=Width-( _BubbleIndent+_BubbleSpacing+SystemInformation.VerticalScrollBarWidth );
} else {
b.Width=Width-( _BubbleIndent+_BubbleSpacing );
}
if ( Position==BubblePositionEnum.Right ) {
b.Left = _BubbleIndent;
b.BubbleColor = _RightBubbleColor;
b.ForeColor = _RightBubbleTextColor;
} else {
b.Left = _BubbleSpacing;
b.BubbleColor=_LeftBubbleColor;
b.ForeColor=_LeftBubbleTextColor;
}
this.Messages.Add(b);
this.Controls.Add(b);
if ( Messages.Count>_TruncateHistory&&_TruncateHistory>0 ) {
Remove( Messages[0] );
this.Invalidate();
}
base.ScrollControlIntoView(this.Controls[Controls.Count-1]);
}
public void Truncate( int count ) {
if ( count>=( Controls.Count-1 ) ) {
// Controls.Clear();
Messages.Clear();
} else if ( count>1 ) {
int x=0;
while ( x<count&&x<=Controls.Count ) {
Messages.RemoveAt( 0 );
x++;
}
} else {
Messages.RemoveAt(0);
}
this.Invalidate();
RedrawControls();
}
protected override void OnResize( System.EventArgs e ) {
RedrawControls();
base.OnResize( e );
}
private void RedrawControls() {
int count=0;
Message last=null;
int new_width=this.Width;
this.Controls.Clear();
VerticalScroll.Visible = false;
this.SuspendLayout();
foreach ( Message m in this.Messages ) {
if ( count>0 ) {
m.Top=last.Top+last.Height+_BubbleSpacing;
if ( VerticalScroll.Visible ) {
m.Width=new_width-( _BubbleIndent+_BubbleSpacing+SystemInformation.VerticalScrollBarWidth );
} else {
m.Width=new_width-( _BubbleIndent+_BubbleSpacing );
}
} else {
m.Top=_BubbleSpacing;
if ( VerticalScroll.Visible ) {
m.Width=new_width-( _BubbleIndent+_BubbleSpacing+SystemInformation.VerticalScrollBarWidth );
} else {
m.Width=new_width-( _BubbleIndent+_BubbleSpacing );
}
}
last=m;
count++;
}
this.Controls.AddRange(Messages.ToArray<Message>());
if ( this.Controls.Count>0 ) {
base.ScrollControlIntoView( this.Controls[Controls.Count-1] );
}
this.ResumeLayout();
}
public class Message : RichTextBox {
private GraphicsPath Shape;
private Color _TextColor=Color.FromArgb( 52, 52, 52 );
private Color _BubbleColor=Color.FromArgb( 217, 217, 217 );
private bool _DrawBubbleArrow=true;
private BubblePositionEnum _BubblePosition = BubblePositionEnum.Left;
public override Color ForeColor { get { return this._TextColor; } set { this._TextColor=value; this.Invalidate(); } }
public BubblePositionEnum BubblePosition { get { return this._BubblePosition; } set { this._BubblePosition=value; this.Invalidate(); } }
public Color BubbleColor { get { return this._BubbleColor; } set { this._BubbleColor=value; this.Invalidate(); } }
public bool DrawBubbleArrow { get { return _DrawBubbleArrow; } set { _DrawBubbleArrow=value; Invalidate(); } }
public Message(BubblePositionEnum Position) {
_BubblePosition=Position;
SetStyle( ControlStyles.AllPaintingInWmPaint|ControlStyles.OptimizedDoubleBuffer|ControlStyles.ResizeRedraw|ControlStyles.SupportsTransparentBackColor|ControlStyles.UserPaint, true );
DoubleBuffered=true;
Size=new Size( 152, 38 );
BackColor=Color.Transparent;
ForeColor=Color.FromArgb( 52, 52, 52 );
Font=new Font( "Segoe UI", 10 );
Anchor=AnchorStyles.Top|AnchorStyles.Left|AnchorStyles.Right;
BorderStyle=System.Windows.Forms.BorderStyle.None;
ScrollBars = RichTextBoxScrollBars.None;
}
[DllImport( "kernel32.dll", CharSet=CharSet.Auto )]
static extern IntPtr LoadLibrary( string lpFileName );
protected override CreateParams CreateParams {
get {
CreateParams prams=base.CreateParams;
if ( LoadLibrary( "msftedit.dll" )!=IntPtr.Zero ) {
prams.ExStyle|=0x020; // transparent
prams.ClassName="RICHEDIT50W";
}
return prams;
}
}
protected override void OnResize( System.EventArgs e ) {
SuspendLayout();
Shape=new GraphicsPath();
var _Shape=Shape;
if ( BubblePosition==BubblePositionEnum.Left ) {
_Shape.AddArc( 9, 0, 10, 10, 180, 90 );
_Shape.AddArc( Width-11, 0, 10, 10, -90, 90 );
_Shape.AddArc( Width-11, Height-11, 10, 10, 0, 90 );
_Shape.AddArc( 9, Height-11, 10, 10, 90, 90 );
} else {
_Shape.AddArc( 0, 0, 10, 10, 180, 90 );
_Shape.AddArc( Width-18, 0, 10, 10, -90, 90 );
_Shape.AddArc( Width-18, Height-11, 10, 10, 0, 90 );
_Shape.AddArc( 0, Height-11, 10, 10, 90, 90 );
}
_Shape.CloseAllFigures();
Bitmap B=new Bitmap( this.Width, this.Height );
Graphics G=Graphics.FromImage( B );
SizeF s=G.MeasureString( Text, Font, Width-25 );
this.Height=(int)( Math.Floor( s.Height )+10 );
ResumeLayout();
//Invalidate();
base.OnResize( e );
}
protected override void OnClick( EventArgs e ) {
//MessageBox.Show( base.Height.ToString() );
base.OnClick( e );
}
protected override void OnPaint( PaintEventArgs e ) {
base.OnPaint( e );
Bitmap B=new Bitmap( this.Width, this.Height );
Graphics G=Graphics.FromImage( B );
B=new Bitmap( this.Width, this.Height );
G=Graphics.FromImage( B );
var _G=G;
_G.SmoothingMode=SmoothingMode.HighQuality;
_G.PixelOffsetMode=PixelOffsetMode.HighQuality;
_G.Clear( BackColor );
// Fill the body of the bubble with the specified color
_G.FillPath( new SolidBrush( _BubbleColor ), Shape );
// Draw the string specified in 'Text' property
// if ( _BubblePosition==BubblePositionEnum.Left ) {
// _G.DrawString( Text, Font, new SolidBrush( ForeColor ), new Rectangle( 13, 4, Width-19, Height-5 ) );
// } else {
// _G.DrawString( Text, Font, new SolidBrush( ForeColor ), new Rectangle( 5, 4, Width-19, Height-5 ) );
// }
// Draw a polygon on the right side of the bubble
if ( _DrawBubbleArrow==true ) {
if(_BubblePosition == BubblePositionEnum.Left) {
Point[] p = {
new Point(9, 9),
new Point(0, 15),
new Point(9, 20)
};
_G.FillPolygon( new SolidBrush( _BubbleColor ), p );
_G.DrawPolygon( new Pen( new SolidBrush( _BubbleColor ) ), p );
} else {
Point[] p = {
new Point(Width - 8, 9),
new Point(Width, 15),
new Point(Width - 8, 20)
};
_G.FillPolygon( new SolidBrush( _BubbleColor ), p );
_G.DrawPolygon( new Pen( new SolidBrush( _BubbleColor ) ), p );
}
}
G.Dispose();
e.Graphics.InterpolationMode=InterpolationMode.HighQualityBicubic;
e.Graphics.DrawImageUnscaled( B, 0, 0 );
B.Dispose();
}
}
}
以防万一不清楚,我不想在上面绘制文字,因为你可以看到我对此没有任何问题。我希望在图形上呈现自然文本,同时保留使用 RichTextBox 控件的所有功能,例如
(对于那些在我将其变为现实时忍受这一点的人,由于社区的支持,我将将该控件的最终版本发布回社区 - 高度依赖于进度 ^^ - 正如您所知,主要的工作已经完成,所以除了这个微小的细节之外,一切都应该是为了添加所有其他的好处。)
与其在源自
OnPaint
的控件的 RichTextBox
中绘制内容,不如在仅包含文本框的用户控件上的文本框周围绘制内容,并让文本框自行绘制。
[![消息新控件][1]][1] 这是更新后的代码,尝试了多种方法使其工作
可点击链接已解决 您可以获取和设置内联字体样式更改 嵌入表情(图像)的可能性仍有待确定 完全可选的文本已解决 右键选项已解决
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using static MessageNewControl;
public class MessageNewControl : ScrollableControl
{
public List<MessageNew> MessageNews { get; private set; }
private Color _LeftBubbleColor = Color.FromArgb(217, 217, 217);
private Color _RightBubbleColor = Color.FromArgb(192, 206, 215);
private Color _LeftBubbleTextColor = Color.FromArgb(52, 52, 52);
private Color _RightBubbleTextColor = Color.FromArgb(52, 52, 52);
private bool _DrawArrow = true;
private int _BubbleIndent = 40;
private int _BubbleSpacing = 10;
private int _TruncateHistory = 0;
public enum BubblePositionEnum { Left, Right }
public Color LeftBubbleColor { get { return _LeftBubbleColor; } set { _LeftBubbleColor = value; } }
public Color RightBubbleColor { get { return _RightBubbleColor; } set { _RightBubbleColor = value; } }
public Color LeftBubbleTextColor { get { return _LeftBubbleTextColor; } set { _LeftBubbleTextColor = value; } }
public Color RightBubbleTextColor { get { return _RightBubbleTextColor; } set { _RightBubbleTextColor = value; } }
public int BubbleIndent { get { return _BubbleIndent; } set { _BubbleIndent = value; } }
public int BubbleSpacing { get { return _BubbleSpacing; } set { _BubbleSpacing = value; } }
public bool DrawArrow { get { return _DrawArrow; } set { _DrawArrow = value; } }
public int TruncatHistory { get { return _TruncateHistory; } set { _TruncateHistory = value; } }
public MessageNewControl()
{
MessageNews = new List<MessageNew>();
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
DoubleBuffered = true;
BackColor = Color.FromArgb(128,Color.Orange);
Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
AutoScroll = true;
}
public void Remove(MessageNew message)
{
this.Invalidate();
MessageNews.Remove(message);
RedrawControls();
}
public void Remove(MessageNew[] messages)
{
foreach (MessageNew m in messages)
{
MessageNews.Remove(m);
}
RedrawControls();
this.Invalidate();
}
public void Add(string MessageNew, BubblePositionEnum Position)
{
if (MessageNews.Count > 0)
{
MessageNew m = MessageNews[MessageNews.Count - 1];
if (m.BubblePosition == Position)
{
MessageNew = m.Text + "\n" + MessageNew;
Remove(m);
}
}
MessageNew b = new MessageNew(Position);
if (MessageNews.Count > 0)
{
b.Top = MessageNews[MessageNews.Count - 1].Top + MessageNews[MessageNews.Count - 1].Height + _BubbleSpacing;
}
else
{
b.Top = _BubbleSpacing;
}
b.Text = MessageNew;
b.DrawBubbleArrow = _DrawArrow;
if (VerticalScroll.Visible)
{
b.Width = Width - (_BubbleIndent + _BubbleSpacing + SystemInformation.VerticalScrollBarWidth);
}
else
{
b.Width = Width - (_BubbleIndent + _BubbleSpacing);
}
if (Position == BubblePositionEnum.Right)
{
b.Left = _BubbleIndent;
b.BubbleColor = _RightBubbleColor;
b.ForeColor = _RightBubbleTextColor;
}
else
{
b.Left = _BubbleSpacing;
b.BubbleColor = _LeftBubbleColor;
b.ForeColor = _LeftBubbleTextColor;
}
this.MessageNews.Add(b);
this.Controls.Add(b);
if (MessageNews.Count > _TruncateHistory && _TruncateHistory > 0)
{
Remove(MessageNews[0]);
this.Invalidate();
}
base.ScrollControlIntoView(this.Controls[Controls.Count - 1]);
}
public void Truncate(int count)
{
if (count >= (Controls.Count - 1))
{
// Controls.Clear();
MessageNews.Clear();
}
else if (count > 1)
{
int x = 0;
while (x < count && x <= Controls.Count)
{
MessageNews.RemoveAt(0);
x++;
}
}
else
{
MessageNews.RemoveAt(0);
}
this.Invalidate();
RedrawControls();
}
protected override void OnResize(System.EventArgs e)
{
RedrawControls();
base.OnResize(e);
}
private void RedrawControls()
{
int count = 0;
MessageNew last = null;
int new_width = this.Width;
this.Controls.Clear();
VerticalScroll.Visible = false;
this.SuspendLayout();
foreach (MessageNew m in this.MessageNews)
{
if (count > 0)
{
m.Top = last.Top + last.Height + _BubbleSpacing;
if (VerticalScroll.Visible)
{
m.Width = new_width - (_BubbleIndent + _BubbleSpacing + SystemInformation.VerticalScrollBarWidth);
}
else
{
m.Width = new_width - (_BubbleIndent + _BubbleSpacing);
}
}
else
{
m.Top = _BubbleSpacing;
if (VerticalScroll.Visible)
{
m.Width = new_width - (_BubbleIndent + _BubbleSpacing + SystemInformation.VerticalScrollBarWidth);
}
else
{
m.Width = new_width - (_BubbleIndent + _BubbleSpacing);
}
}
last = m;
count++;
}
this.Controls.AddRange(MessageNews.ToArray<MessageNew>());
if (this.Controls.Count > 0)
{
base.ScrollControlIntoView(this.Controls[Controls.Count - 1]);
}
this.ResumeLayout();
}
}
[ToolboxBitmap(typeof(RichTextBox))]
public class MessageNew : RichTextBox, IMessageFilter
{
private GraphicsPath Shape;
private Color _TextColor = Color.FromArgb(52, 152, 152);
private Color _BubbleColor = Color.FromArgb(217, 217, 217);
private bool _DrawBubbleArrow = true;
private BubblePositionEnum _BubblePosition = BubblePositionEnum.Left;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == 0x20a) // WM_MOUSEWHEEL
{
OnMouseWheel(new MouseEventArgs(MouseButtons.None, 0, 0, 0, (short)((m.WParam.ToInt32() >> 16) & 0xffff)));
return true;
}
return false;
}
protected override void OnLinkClicked(LinkClickedEventArgs e)
{
System.Diagnostics.Process.Start(e.LinkText);
}
public override Color ForeColor { get { return this._TextColor; } set { this._TextColor = value; this.Invalidate(); } }
public BubblePositionEnum BubblePosition { get { return this._BubblePosition; } set { this._BubblePosition = value; this.Invalidate(); } }
public Color BubbleColor { get { return this._BubbleColor; } set { this._BubbleColor = value; this.Invalidate(); } }
public bool DrawBubbleArrow { get { return _DrawBubbleArrow; } set { _DrawBubbleArrow = value; Invalidate(); } }
public MessageNew(BubblePositionEnum Position)
{
_BubblePosition = Position;
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
DoubleBuffered = true;
Size = new Size(152, 38);
BackColor = Color.Transparent;
ForeColor = Color.FromArgb(52, 52, 52);
Font = new Font("Segoe UI", 10);
Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
BorderStyle = System.Windows.Forms.BorderStyle.None;
ScrollBars = RichTextBoxScrollBars.None;
this.SelectionChanged += MessageNew_SelectionChanged; // Hook up event handler
}
private void MessageNew_SelectionChanged(object sender, EventArgs e)
{
HighlightSelectedText();
}
private void HighlightSelectedText()
{
// Get the current selection start and length
int start = this.SelectionStart;
int length = this.SelectionLength;
// Highlight the selected text
this.SelectionBackColor = Color.Yellow;
// Move the selection back to its original position
this.SelectionStart = start;
this.SelectionLength = length;
}
protected override void OnResize(System.EventArgs e)
{
SuspendLayout();
Shape = new GraphicsPath();
//var _Shape = Shape;
//if (BubblePosition == BubblePositionEnum.Left)
//{
// _Shape.AddArc(9, 0, 10, 10, 180, 90);
// _Shape.AddArc(Width - 11, 0, 10, 10, -90, 90);
// _Shape.AddArc(Width - 11, Height - 11, 10, 10, 0, 90);
// _Shape.AddArc(9, Height - 11, 10, 10, 90, 90);
//}
var _Shape = Shape;
if (BubblePosition == BubblePositionEnum.Left)
{
_Shape.AddArc(0, 0, 10, 10, 180, 90);
_Shape.AddArc(Width - 11, 0, 10, 10, -90, 90);
_Shape.AddArc(Width - 11, Height - 11, 10, 10, 0, 90);
_Shape.AddArc(0, Height - 11, 10, 10, 90, 90);
}
else
{
_Shape.AddArc(0, 0, 10, 10, 180, 90);
_Shape.AddArc(Width - 18, 0, 10, 10, -90, 90);
_Shape.AddArc(Width - 18, Height - 11, 10, 10, 0, 90);
_Shape.AddArc(0, Height - 11, 10, 10, 90, 90);
}
_Shape.CloseAllFigures();
Bitmap B = new Bitmap(this.Width, this.Height);
Graphics G = Graphics.FromImage(B);
SizeF s = G.MeasureString(Text, Font, Width - 25);
this.Height = (int)(Math.Floor(s.Height) + 10);
ResumeLayout();
//Invalidate();
base.OnResize(e);
}
protected override void OnClick(EventArgs e)
{
//MessageNewBox.Show( base.Height.ToString() );
base.OnClick(e);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Bitmap B = new Bitmap(this.Width, this.Height);
Graphics G = Graphics.FromImage(B);
B = new Bitmap(this.Width, this.Height);
G = Graphics.FromImage(B);
var _G = G;
_G.SmoothingMode = SmoothingMode.HighQuality;
_G.PixelOffsetMode = PixelOffsetMode.HighQuality;
_G.Clear(BackColor);
// Fill the body of the bubble with the specified color
_G.FillPath(new SolidBrush(_BubbleColor), Shape);
////Draw the string specified in 'Text' property
// if (_BubblePosition == BubblePositionEnum.Left)
//{
// _G.DrawString(Text, Font, new SolidBrush(ForeColor), new Rectangle(13, 4, Width - 19, Height - 5));
//}
//else
//{
// _G.DrawString(Text, Font, new SolidBrush(ForeColor), new Rectangle(5, 4, Width - 19, Height - 5));
//}
// Draw a polygon on the right side of the bubble
if (_DrawBubbleArrow == true)
{
//if (_BubblePosition == BubblePositionEnum.Left)
//{
// Point[] p = {
// new Point(9, 9),
// new Point(0, 15),
// new Point(9, 20)
// };
// _G.FillPolygon(new SolidBrush(Color.Black), p);
// _G.DrawPolygon(new Pen(new SolidBrush(_BubbleColor)), p);
//}
//else
//{
// Point[] p = {
// new Point(Width - 8, 9),
// new Point(Width, 15),
// new Point(Width - 8, 20)
// };
// _G.FillPolygon(new SolidBrush(_BubbleColor), p);
// _G.DrawPolygon(new Pen(new SolidBrush(_BubbleColor)), p);
//}
}
G.Dispose();
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.DrawImageUnscaled(B, 0, 0);
B.Dispose();
// Draw highlight selection
if (isHighlighting)
{
using (Brush brush = new SolidBrush(Color.FromArgb(128, Color.HotPink)))
{
e.Graphics.FillRectangle(brush, highlightRect);
}
}
// Render text on a transparent background
using (Brush brush = new SolidBrush(this.ForeColor))
{
e.Graphics.DrawString(this.Text, this.Font, brush, 0, 0);
}
// Draw hyperlinks
foreach (LinkArea linkArea in GetLinkAreas())
{
string linkText = this.Text.Substring(linkArea.Start, linkArea.Length);
RectangleF rect = GetTextRectangle(linkArea);
e.Graphics.DrawString(linkText, this.Font, Brushes.Blue, rect);
}
base.OnPaint(e);
}
// --------------------To Open Links browser
private IEnumerable<LinkArea> GetLinkAreas()
{
List<LinkArea> linkAreas = new List<LinkArea>();
// Implement the logic to identify link areas in the text
// For example:
int startIndex = this.Text.IndexOf("http://");
while (startIndex != -1)
{
int endIndex = this.Text.IndexOf(" ", startIndex);
if (endIndex == -1)
endIndex = this.Text.Length - 1;
LinkArea linkArea = new LinkArea(startIndex, endIndex - startIndex);
linkAreas.Add(linkArea);
startIndex = this.Text.IndexOf("http://", endIndex);
}
return linkAreas;
}
private RectangleF GetTextRectangle(LinkArea linkArea)
{
// Get the position of the start and end characters of the link area
PointF startPoint = GetPositionFromCharIndex(linkArea.Start);
PointF endPoint = GetPositionFromCharIndex(linkArea.Start + linkArea.Length);
// Calculate the width and height of the rectangle
float width = endPoint.X - startPoint.X;
float height = endPoint.Y - startPoint.Y;
// Create and return the rectangle
return new RectangleF(startPoint.X, startPoint.Y, width, height);
}
private const int WS_EX_TRANSPARENT = 0x20;
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
public MessageNew()
{
SetStyle(
ControlStyles.SupportsTransparentBackColor |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer, true);
//SetStyle(ControlStyles.UserPaint, true);
BackColor = Color.Transparent;
Font = new Font(Font.FontFamily, 20);
}
//---------------------To Make It transparent
[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string lpFileName);
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20; // WS_EX_TRANSPARENT
if (LoadLibrary("msftedit.dll") != IntPtr.Zero)
{
cp.ClassName = "RICHEDIT50W"; //-----------behave like richtextbox If you want it to be TextBox change "RICHEDIT50W" to "EDIT"
}
else if (LoadLibrary("riched20.dll") != IntPtr.Zero)
{
cp.ClassName = "RichEdit20W";
}
return cp;
}
}
//----------------------------For Text Selection
private const int EM_GETSEL = 0xB0;
private const int EM_GETRECT = 0xB2;
private const int EM_SETRECT = 0xB3;
private const int EM_HIDESELECTION = 0x201;
private const int EM_EXGETSEL = 0x00B8;
private const int EM_EXSETSEL = 0x00B1;
private bool isHighlighting = false;
private Rectangle highlightRect;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case EM_GETRECT:
RECT rect = (RECT)m.GetLParam(typeof(RECT));
if (isHighlighting)
{
rect.Top = highlightRect.Top;
rect.Bottom = highlightRect.Bottom;
Marshal.StructureToPtr(rect, m.LParam, true);
}
break;
}
}
protected override void OnSelectionChanged(EventArgs e)
{
base.OnSelectionChanged(e);
if (SelectionLength > 0)
{
isHighlighting = true;
int start = SelectionStart;
int end = start + SelectionLength;
Point startPt = GetPositionFromCharIndex(start);
Point endPt = GetPositionFromCharIndex(end);
highlightRect = new Rectangle(startPt, new Size(endPt.X - startPt.X, Font.Height));
Invalidate();
}
else
{
isHighlighting = false;
Invalidate();
}
}
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
private ContextMenuStrip CreateCustomContextMenu()
{
ContextMenuStrip contextMenu = new ContextMenuStrip();
// Undo
ToolStripMenuItem undoMenuItem = new ToolStripMenuItem("Undo");
undoMenuItem.ShortcutKeys = Keys.Control | Keys.Z; // Set Ctrl+Z as the shortcut key
undoMenuItem.Click += (sender, e) => Undo();
contextMenu.Items.Add(undoMenuItem);
// Cut
ToolStripMenuItem cutMenuItem = new ToolStripMenuItem("Cut");
cutMenuItem.ShortcutKeys = Keys.Control | Keys.X; // Set Ctrl+X as the shortcut key
cutMenuItem.Click += (sender, e) => Cut();
contextMenu.Items.Add(cutMenuItem);
// Copy
ToolStripMenuItem copyMenuItem = new ToolStripMenuItem("Copy");
copyMenuItem.ShortcutKeys = Keys.Control | Keys.C; // Set Ctrl+C as the shortcut key
copyMenuItem.Click += (sender, e) => Copy();
contextMenu.Items.Add(copyMenuItem);
// Paste
ToolStripMenuItem pasteMenuItem = new ToolStripMenuItem("Paste");
pasteMenuItem.ShortcutKeys = Keys.Control | Keys.V; // Set Ctrl+V as the shortcut key
pasteMenuItem.Click += (sender, e) => Paste();
contextMenu.Items.Add(pasteMenuItem);
// Select All
ToolStripMenuItem selectAllMenuItem = new ToolStripMenuItem("Select All");
selectAllMenuItem.ShortcutKeys = Keys.Control | Keys.A; // Set Ctrl+A as the shortcut key
selectAllMenuItem.Click += (sender, e) => SelectAll();
contextMenu.Items.Add(selectAllMenuItem);
return contextMenu;
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
UpdateStyles();
if (ContextMenuStrip == null)
{
ContextMenuStrip = CreateCustomContextMenu();
}
}
}
以及使用
using System;
using System.Windows.Forms;
namespace testApp
{
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// You can add a message to the right side
messageNewControl1.Add("This is a right side message https://www.youtube.com/@Amro-Omran "+"\n"+ "Please Like And subscribe For More useful Codes", MessageNewControl.BubblePositionEnum.Right);
}
private void button2_Click(object sender, EventArgs e)
{
// You can add a message to the left side
messageNewControl1.Add("This is a left side message ", MessageNewControl.BubblePositionEnum.Left);
}
private void button4_Click(object sender, EventArgs e)
{
// You can add a message to the left side
messageNewControl1.Truncate(0);
}
private void button3_Click(object sender, EventArgs e)
{
// Define the index of the message you want to remove
int index = 0; // Replace 0 with the actual index you want to remove
// Check if the index is within the valid range before attempting to remove the message
if (index >= 0 && index < messageNewControl1.MessageNews.Count)
{
// Remove the message at the specified index
messageNewControl1.Remove(messageNewControl1.MessageNews[index]);
}
else
{
// Handle the case where the index is out of range
Console.WriteLine("Index is out of range.");
}
}
private void Form4_Load(object sender, EventArgs e)
{
}
}
}
namespace testApp
{
partial class Form4
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form4));
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.messageNewControl1 = new MessageNewControl();
this.SuspendLayout();
//
// button1
//
this.button1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));
this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.button1.ForeColor = System.Drawing.Color.Cornsilk;
this.button1.Location = new System.Drawing.Point(75, 353);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(115, 30);
this.button1.TabIndex = 1;
this.button1.Text = "Add Right";
this.button1.UseVisualStyleBackColor = false;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));
this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.button2.ForeColor = System.Drawing.Color.Cornsilk;
this.button2.Location = new System.Drawing.Point(228, 353);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(115, 30);
this.button2.TabIndex = 3;
this.button2.Text = "Add Left";
this.button2.UseVisualStyleBackColor = false;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// button3
//
this.button3.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));
this.button3.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.button3.ForeColor = System.Drawing.Color.Cornsilk;
this.button3.Location = new System.Drawing.Point(549, 353);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(145, 30);
this.button3.TabIndex = 5;
this.button3.Text = "Remove By Index";
this.button3.UseVisualStyleBackColor = false;
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// button4
//
this.button4.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));
this.button4.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.button4.ForeColor = System.Drawing.Color.Cornsilk;
this.button4.Location = new System.Drawing.Point(381, 353);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(130, 30);
this.button4.TabIndex = 4;
this.button4.Text = "Remove Index 0";
this.button4.UseVisualStyleBackColor = false;
this.button4.Click += new System.EventHandler(this.button4_Click);
//
// messageNewControl1
//
this.messageNewControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.messageNewControl1.AutoScroll = true;
this.messageNewControl1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(200)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
this.messageNewControl1.BubbleIndent = 40;
this.messageNewControl1.BubbleSpacing = 10;
this.messageNewControl1.DrawArrow = true;
this.messageNewControl1.Font = new System.Drawing.Font("Tahoma", 20F);
this.messageNewControl1.LeftBubbleColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));
this.messageNewControl1.LeftBubbleTextColor = System.Drawing.Color.White;
this.messageNewControl1.Location = new System.Drawing.Point(32, 27);
this.messageNewControl1.Name = "messageNewControl1";
this.messageNewControl1.RightBubbleColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(0)))));
this.messageNewControl1.RightBubbleTextColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(255)))));
this.messageNewControl1.Size = new System.Drawing.Size(692, 277);
this.messageNewControl1.TabIndex = 8;
this.messageNewControl1.Text = "messageNewControl1";
this.messageNewControl1.TruncatHistory = 0;
//
// Form4
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.ControlLightLight;
this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage")));
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.ClientSize = new System.Drawing.Size(770, 456);
this.Controls.Add(this.messageNewControl1);
this.Controls.Add(this.button3);
this.Controls.Add(this.button4);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "Form4";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Form4";
this.Load += new System.EventHandler(this.Form4_Load);
this.ResumeLayout(false);
}
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
private MessageNewControl messageNewControl1;
}
}
[1]: https://i.stack.imgur.com/biyP1.jpg