透明的RichTextBox,图形不显示文本

时间:2015-06-11 08:10:30

标签: c# winforms graphics transparency richtextbox

我有以下代码工作,并注释掉正在绘制到控件上的Text,因为我开始使用它作为仅图形控件。继续,我已将控件切换为RichTextBox而不是Control,以便我可以拥有随附的所有好东西,例如可点击的超链接,可选择的文本等。

我面临的问题是,文本可以被选中,甚至被复制,但它是不可见的,并且也没有准确定位到我想要的位置(取消注释Messages.OnPaint()方法中的文本打印行看看我希望文本如何出现)

问题的漂亮图片 enter image description here

我想要做什么的简洁图片 enter image description here

图片打印代码无法显示的内容的简洁图片 enter image description here

代码

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控件的所有功能,例如

  • 可点击链接
  • 内联字体样式更改
  • 嵌入表情(图像)的可能性
  • 完全可选择的文字
  • 右键单击选项
  • 未列出的其他内容,但在聊天/消息控制方面非常酷。

(对于那些带着这一点的人,由于社区的支持,我将把这个带到生活中,我将把这个控制的最终版本发回社区 - 高度依赖于进展^^ - 你可以说,工作的主要部分已经完成,所以除了这个细节之外,一切都应该是为了添加所有其他好东西。)

1 个答案:

答案 0 :(得分:0)

而不是在OnPaint得出的RichTextBox控件中绘制内容,而不是在文本框周围绘制内容,包含文本框的用户控件,并让文本更好盒子自我画。