0

パイプ(オイルパイプ)を表す直線がたくさんあるプログラムがあります。線は、次の垂直線のサンプル コードを使用して、各コントロールの Paint イベントで線が描画されるユーザー コントロールです。

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

問題は、パイプ内のオイルの流れ方向を表示したいため、何らかの形で矢印を追加する必要があることです。StartCap と EndCap は、次の理由によりここでは機能しません。

ユーザーコントロール自体は、線の周りに「デッド」領域がないように、線(パイプ)の幅と正確に一致する必要があります。これは、後でフォームの他のユーザーコントロールと重なります。StartCap または EndCap を使用し、たとえば 2 ピクセルの線幅を使用する場合、矢印 (StartCap または EndCap) を描画するには、ユーザー コントロールの幅を広くする必要があります。

簡単な方法は、「空の」領域を透明にすることですが、非常に長い間グーグルで検索した後、あきらめました。ユーザーコントロールでこれを達成するための信頼できる方法はないようです。

次に、矢印のみを描画する別のユーザー コントロールを作成できると考えましたが、他のユーザー コントロールを覆う未描画領域にまだ問題があります。

誰もが次のいずれかの方法を提案していますか?

  • 描画されていないユーザー コントロール領域を透明にしますか?
  • 上記を達成するための他のアプローチはありますか?

私の「パイプ」は幅が 2 ピクセルしかないため、線/パイプ内に何かを描画する可能性はありません :(

提案/コメントは大歓迎です!

4

1 に答える 1

3

コントロールの背景を透明にする方法がありますwinforms(互いに重なり合って)。ただし、実行時にコントロールを移動すると、ちらつくことがあります。もう 1 つの選択肢は、 を使用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);
    }
}

結果は次のとおりです。

ここに画像の説明を入力

を使用BackColorして、矢印の色を変更できます。矢印を描画するだけでよい場合は、特にSystem.Drawing.Drawing2D.AdjustableArrowCapプロパティCustomStartCapとを使用して処理することで、コードはより単純になりCustomEndCapます。ただし、要件に関してRegionは、多くの場合、を使用することがほぼ最良の選択です。

アップデート

クリッピングの代わりにandを使用するトランスペアレントを使用したソリューションが必要な場合はBackground、をから継承する必要があります。コードは次のとおりです。PenCustomLineCapRegionVerticalArrowControl

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 colorForeColorます。

于 2013-08-01T15:57:26.873 に答える