用透明背景绘制形状

时间:2013-08-01 13:51:48

标签: c# winforms gdi+

我有一个程序,有很多直线代表管道(油管)。 这些行是用户控件,其中在每个控件的Paint事件中绘制线条,并使用以下示例代码表示垂直线:

e.Graphics.DrawLine(linePen, new Point(0, 0), new Point(0, this.Height));

问题在于我想显示管道中油的流向,因此需要以某种方式添加箭头。 由于以下原因,StartCap和EndCap在此处不起作用:

用户控件本身必须正好是行(管道)的宽度,才能在行周围没有任何“死”区域,这将与我以后的表单上的其他用户控件重叠。 如果使用StartCap或EndCap,并且线宽例如是2像素,用户控件必须更宽,才能绘制箭头(StartCap或EndCap)。

简单的方法是让“空”区域透明,但在谷歌搜索很长一段时间后我放弃了;似乎没有一种可靠的方法来实现用户控制。

然后我想我可以创建一个单独的用户控件,只能绘制箭头,但是我仍然遇到覆盖其他用户控件的未绘制区域的问题。

有没有人建议如何:

  • 使用户控制区域不是透明的?
  • 实现上述目的的其他一些方法?

由于我的“管道”只有2像素宽,因此无法在线/管道内绘制任何内容:(

非常感谢任何建议/意见!

1 个答案:

答案 0 :(得分:3)

有一种方法可以使winforms中的控件背景透明(彼此重叠)。但是,在运行时移动控件可能会使其闪烁。另一种选择是使用Region来指定控件的区域,以便理论上它具有任何形状。这就是我能为你做的,只是一个演示:

public partial class VerticalArrow : UserControl
{
    public VerticalArrow()
    {
        InitializeComponent();
        Direction = ArrowDirection.Up;                       
    }
    public enum ArrowDirection
    {
        Up,
        Down
    }
    ArrowDirection dir;
    public ArrowDirection Direction
    {
        get { return dir; }
        set
        {
            if (dir != value)
            {
                dir = value;
                UpdateRegion();
            }
        }
    }
    //default values of ArrowWidth and ArrowHeight
    int arrowWidth = 14;
    int arrowHeight = 18;
    public int ArrowWidth
    {
        get { return arrowWidth; }
        set
        {
            if (arrowWidth != value)
            {
                arrowWidth = value;
                UpdateRegion();                    
            }
        }
    }
    public int ArrowHeight
    {
        get { return arrowHeight; }
        set
        {
            if (arrowHeight != value)
            {
                arrowHeight = value;
                UpdateRegion();
            }
        }
    }
    //This will keep the size of the UserControl fixed at design time.
    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
    {
        base.SetBoundsCore(x, y, Math.Max(ArrowWidth, 4), height, specified);
    }        
    private void UpdateRegion()
    {            
        GraphicsPath gp = new GraphicsPath();
        int dx = ArrowWidth / 2 - 1;
        int dy = ArrowHeight / 2;
        Point p1 = new Point(dx, Direction == ArrowDirection.Up ? dy : 1);
        Point p2 = new Point(ArrowWidth - dx, Direction == ArrowDirection.Up ? dy + 1: 1);
        Point p3 = new Point(ArrowWidth - dx, Direction == ArrowDirection.Up ? ClientSize.Height : ClientSize.Height - dy);
        Point p4 = new Point(dx, Direction == ArrowDirection.Up ? ClientSize.Height : ClientSize.Height - dy);
        Point q1 = Direction == ArrowDirection.Up ? new Point(0, ArrowHeight) : new Point(0, ClientSize.Height - ArrowHeight);
        Point q2 = Direction == ArrowDirection.Up ? new Point(dx, 0) : new Point(dx, ClientSize.Height);
        Point q3 = Direction == ArrowDirection.Up ? new Point(ArrowWidth, ArrowHeight) : new Point(ArrowWidth, ClientSize.Height - ArrowHeight);
        if (Direction == ArrowDirection.Up) gp.AddPolygon(new Point[] { p1, q1, q2, q3, p2, p3, p4 });
        else gp.AddPolygon(new Point[] {p1,p2,p3,q3,q2,q1,p4});
        Region = new Region(gp);
    }
    protected override void OnSizeChanged(EventArgs e)
    {
        UpdateRegion();
        base.OnSizeChanged(e);
    }
}

结果如下:

enter image description here

您可以使用BackColor更改箭头的颜色。如果我们只需要绘制箭头,代码就会更简单,特别是在System.Drawing.Drawing2D.AdjustableArrowCap的帮助下处理属性CustomStartCapCustomEndCap。但是,根据您的要求,在许多情况下使用Region几乎是最佳选择。

更新

如果您希望使用透明Background的解决方案,我们使用PenCustomLineCap而不是剪切RegionVerticalArrow必须继承{ {1}}。这是代码:

Control

截图:

enter image description here

要更改public class VerticalArrow : Control { public VerticalArrow() { Width = 30; Height = 100; Direction = ArrowDirection.Up; ArrowHeight = 4; ArrowWidth = 4; TrunkWidth = 2; SetStyle(ControlStyles.Opaque, true); } protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x20; return cp; } } public ArrowDirection Direction { get; set; } public int ArrowHeight { get; set; } public int ArrowWidth { get; set; } public int TrunkWidth { get; set; } Point p1, p2; public enum ArrowDirection { Up, Down, UpDown } protected override void OnSizeChanged(EventArgs e) { p1 = new Point(Width / 2, 0); p2 = new Point(Width / 2, Height); base.OnSizeChanged(e); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); using (Pen p = new Pen(ForeColor)) { using (AdjustableArrowCap cap = new AdjustableArrowCap(ArrowWidth, ArrowHeight)) { if (Direction == ArrowDirection.Up || Direction == ArrowDirection.UpDown) p.CustomStartCap = cap; if (Direction == ArrowDirection.Down || Direction == ArrowDirection.UpDown) p.CustomEndCap = cap; } p.Width = TrunkWidth; e.Graphics.DrawLine(p, p1, p2); } } } ,请更改Arrow color

相关问题