我有以下代码工作,并注释掉正在绘制到控件上的Text,因为我开始使用它作为仅图形控件。继续,我已将控件切换为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控件的所有功能,例如
(对于那些带着这一点的人,由于社区的支持,我将把这个带到生活中,我将把这个控制的最终版本发回社区 - 高度依赖于进展^^ - 你可以说,工作的主要部分已经完成,所以除了这个细节之外,一切都应该是为了添加所有其他好东西。)
答案 0 :(得分:0)
而不是在OnPaint
得出的RichTextBox
控件中绘制内容,而不是在文本框周围绘制内容,包含文本框的用户控件,并让文本更好盒子自我画。