首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在形状控件中创建缩进,允许在缩进区域上绘制?

如何在形状控件中创建缩进,允许在缩进区域上绘制?
EN

Stack Overflow用户
提问于 2015-06-17 17:05:08
回答 1查看 82关注 0票数 0

我有一个自定义控件,我正在对其应用形状。该形状具有一个指针(类似于Skype中显示消息是接收消息或发送消息的消息指示符),该指针位于左侧或右侧。

当指示器位于左侧时,控件按预期绘制,但当我将指示符放在右侧时,指示符被放置在控件的右边边界之外。

我想要的缩进,是画左边的“化身”。我还将在右边为时间戳添加另一个缩进。

为了让事情变得更清楚,这里给出了当前和客观行为的图像:

我使用的代码如下:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;



/*
public enum SkyeBubbleColors as Color {
    Right=Color.FromArgb( 229, 247, 253 ),
    Left=Color.FromArgb( 199, 237, 252 )
}
*/

public enum BubbleIndicatorEnum {
    Left,
    Right
}


public class MessageRow : Control, IDisposable {


    public MessageRow() {
        SetStyle( ControlStyles.AllPaintingInWmPaint|ControlStyles.OptimizedDoubleBuffer|ControlStyles.ResizeRedraw|ControlStyles.SupportsTransparentBackColor|ControlStyles.UserPaint, true );
        UpdateStyles();
        DoubleBuffered=true;
        try {
            base.BackColor=this.Parent.BackColor;
        } catch ( Exception ee ) {
            Console.WriteLine( ee.Message );
        }

    }

}

public class Message : Control, IDisposable {


    internal class RTB : RichTextBox {

        protected override void OnLinkClicked( LinkClickedEventArgs e ) {
            System.Diagnostics.Process.Start(e.LinkText);
        }

        public RTB() {
            BorderStyle = System.Windows.Forms.BorderStyle.None;
            BackColor = Color.Orange;
            ForeColor = Color.White;
            ReadOnly = false;
            this.Font=new Font( "Segoe UI", 10 );
            Text="";
            Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
            ScrollBars = RichTextBoxScrollBars.None;
        }

    }

    private RTB _Text;

    private bool _TimestampVisible = false;

    private bool _AvatarVisible=false;
    private int _AvatarWidth { get; set; }
    private Image _Avatar;
    public Image Avatar { 
        get { return _Avatar; }
        set { 
            _Avatar = value;
            if ( _Avatar!=null ) {
                _Avatar = ResizeImage(value, 28, 28);
                _AvatarWidth=40;
            } else {
                _Avatar = value;
                _AvatarWidth = 0;
            }
        }
    }

    public bool AvatarVisible {
        get { return _AvatarVisible; }
        set { _AvatarVisible = value; }
    }

    public Message() {
        SetStyle( ControlStyles.AllPaintingInWmPaint|ControlStyles.OptimizedDoubleBuffer|ControlStyles.ResizeRedraw|ControlStyles.SupportsTransparentBackColor|ControlStyles.UserPaint, true );
        UpdateStyles();
        DoubleBuffered = true;
        _Text = new RTB();
        _Text.ContentsResized+=_Text_ContentsResized;
        _Text.Location = new Point(15+_AvatarWidth,5);
        _Text.Width = Width - (15+_AvatarWidth);
        this.Controls.Add( _Text );
        _Text.Visible = true;
        BubbleIndicator=BubbleIndicatorEnum.Left;
        try {
            base.BackColor=this.Parent.BackColor;
        } catch ( Exception ee ) {
            Console.WriteLine(ee.Message);
        }
        if ( _TimestampVisible ) {

        }
    }

    /// <summary>
    /// Resize the image to the specified width and height.
    /// </summary>
    /// <param name="image">The image to resize.</param>
    /// <param name="width">The width to resize to.</param>
    /// <param name="height">The height to resize to.</param>
    /// <returns>The resized image.</returns>
    private static Bitmap ResizeImage( Image image, int width, int height ) {
        var destRect=new Rectangle( 0, 0, width, height );
        var destImage=new Bitmap( width, height );

        destImage.SetResolution( image.HorizontalResolution, image.VerticalResolution );

        using ( var graphics=Graphics.FromImage( destImage ) ) {
            graphics.CompositingMode=CompositingMode.SourceCopy;
            graphics.CompositingQuality=CompositingQuality.HighQuality;
            graphics.InterpolationMode=InterpolationMode.HighQualityBicubic;
            graphics.SmoothingMode=SmoothingMode.HighQuality;
            graphics.PixelOffsetMode=PixelOffsetMode.HighQuality;

            using ( var wrapMode=new ImageAttributes() ) {
                wrapMode.SetWrapMode( WrapMode.TileFlipXY );
                graphics.DrawImage( image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode );
            }
        }

        return destImage;
    }

    void _Text_ContentsResized( object sender, ContentsResizedEventArgs e ) {
        _Text.Height = e.NewRectangle.Height;
        base.Height = _Text.Height + 10;
    }

    private BubbleIndicatorEnum _BubbleIndicator;

    public BubbleIndicatorEnum BubbleIndicator {
        get { return _BubbleIndicator; }
    set{
            _BubbleIndicator=value;
            if ( value==BubbleIndicatorEnum.Left ) {
                _Text.Location=new Point( 15+_AvatarWidth, 5 );
            } else {
                _Text.Location=new Point( 5+_AvatarWidth, 5 );
            }
            _Text.Width=Width-(20+_AvatarWidth);
            UpdateBubbleIndicator();
            _Text.Refresh();
            Invalidate();
        }
    }

    protected override void OnRegionChanged( EventArgs e ) {
        base.OnRegionChanged( e );
    }

    protected override void OnLocationChanged( EventArgs e ) {
        base.OnLocationChanged( e );
        try {
            base.BackColor=this.Parent.BackColor;
        } catch ( Exception ee ) {
            Console.WriteLine( ee.Message );
        }
    }

    public override string Text {
        get {
            return _Text.Text;
        }
        set {
            _Text.Text = value;
            //_Text.RenderEmotes();
        }
    }

    public override Color ForeColor {
        get {
            return _Text.ForeColor;
        }
        set {
            _Text.ForeColor=value;
        }
    }

    public override Font Font {
        get {
            return _Text.Font;
        }
        set {
            _Text.Font=value;
        }
    }

    private Color _BubbleColor = Color.Orange;

    public Color BubbleColor {
        get {
            return _BubbleColor;
        }
        set {
            _BubbleColor=value;
            _Text.BackColor=value;
            _Text.Refresh();
            Invalidate();
        }
    }


    private GraphicsPath Shape = new GraphicsPath();

    protected override void OnResize( EventArgs e ) {
        base.OnResize( e );
        UpdateBubbleIndicator();
    }

    private void UpdateBubbleIndicator() {
        _Text.BackColor=_BubbleColor;
        Shape=new GraphicsPath();

        if ( BubbleIndicator==BubbleIndicatorEnum.Left ) {
            Shape.AddArc( 9+_AvatarWidth, 0, 10, 10, 180, 90 );
            Shape.AddArc( (Width+_AvatarWidth)-11, 0, 10, 10, -90, 90 );
            Shape.AddArc( ( Width+_AvatarWidth )-11, Height-11, 10, 10, 0, 90 );
            Shape.AddArc( 9+_AvatarWidth, 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.AddArc( 0+_AvatarWidth, 0, 10, 10, 180, 90 );
//              Shape.AddArc( ( Width+_AvatarWidth )-18, 0, 10, 10, -90, 90 );
//              Shape.AddArc( ( Width+_AvatarWidth )-18, Height-11, 10, 10, 0, 90 );
//              Shape.AddArc( 0+_AvatarWidth, Height-11, 10, 10, 90, 90 );
        }

        Shape.CloseAllFigures();
        _Text.Width=Width-(20+_AvatarWidth);
    }



    protected override void OnPaint( PaintEventArgs e ) {

        Point[] p;

        if ( BubbleIndicator==BubbleIndicatorEnum.Left ) {
            p= new Point[] {
                    new Point(9+_AvatarWidth, 9),
                    new Point(0+_AvatarWidth, 15),
                    new Point(9+_AvatarWidth, 20)
            };
        } else {
            p = new Point[] {
                    new Point(Width - 8, 9),
                    new Point(Width, 15),
                    new Point(Width - 8, 20)
            };
        }

        SuspendLayout();
        e.Graphics.Clear( BackColor );
        e.Graphics.SmoothingMode=SmoothingMode.HighQuality;
        e.Graphics.PixelOffsetMode=PixelOffsetMode.HighQuality;
        e.Graphics.FillPath( new SolidBrush( _BubbleColor ), Shape );
        e.Graphics.FillPolygon( new SolidBrush( _BubbleColor ), p );
        e.Graphics.DrawPolygon( new Pen( new SolidBrush( _BubbleColor ) ), p );
        e.Graphics.InterpolationMode=InterpolationMode.HighQualityBicubic;
        if ( _AvatarWidth>0&&_AvatarVisible==true&&_Avatar!=null ) {
            e.Graphics.DrawImageUnscaled( _Avatar, 0, 0);
            e.Graphics.DrawImageUnscaled( new Bitmap( this.Width-_AvatarWidth, this.Height ), _AvatarWidth, 0 );
        } else {
            e.Graphics.DrawImageUnscaled( new Bitmap( this.Width, this.Height ), 0, 0 );
        }
        base.OnPaint( e );
        ResumeLayout();
    }

}

请记住,这些框的高度取决于内容,无论控件的高度如何,指示器都应该是相同的大小和第一行。这个功能已经到位,但我觉得有必要提及,因为我相信缩放形状或绘图艺术会导致指针在位置和宽度/高度上不一致或变形。

如果你注意到,这个区域确实是完美地夹在左边,并且像图像中的第一个例子所示的那样是可画的,但是如果我移动到右边的指针,由于某种原因,我不能再剪辑左边了,这是我的问题的核心。

刚刚注意到,我标记为“正确”的图像中的棕色指示符实际上几乎是正确的。信息气泡的右侧应该有圆角,如红色和橙色信息的左侧所示。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-17 21:07:46

我会改变这些地方:

代码语言:javascript
复制
   if ( BubbleIndicator==BubbleIndicatorEnum.Left ) {
        Shape.AddArc( 9+_AvatarWidth, 0, 10, 10, 180, 90 );
        Shape.AddArc( (Width/*+_AvatarWidth*/)-11, 0, 10, 10, -90, 90 ); // !!
        Shape.AddArc( (Width/*+_AvatarWidth*/ )-11, Height-11, 10, 10, 0, 90 ); //!!

代码语言:javascript
复制
    } else {
        Shape.AddArc( _AvatarWidth, 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(  _AvatarWidth, Height-11, 10, 10, 90, 90 ); //!!

请注意,这是未经测试的!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30897974

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档