Search code examples
c#winformspaintevent

How to override paint eventhandler with derived type of PaintEventArgs


I want to transfer the angle of a line to be drawn via a class AnglePaintEvent Args which is derived from PaintEventArgs class.

    public class AnglePaintEventArgs : PaintEventArgs
{
    int angle;
    public AnglePaintEventArgs(Graphics graphic, Rectangle rectangle, int Angle) : base(graphic, rectangle)
    {
        angle = Angle;
    }
}

The panel’s eventhandler only accepts functions that have the argument PaintEventArgs but not AnglePaintEventArgs. I was not able to cast the args. Several tries:

        public Form1()
    {
        InitializeComponent();
        //tried this
        this.panel1.Paint += new PaintEventHandler(AnglePaintEventArgs);
        //tried that
        this.panel1.Paint += new AnglePaintEventArgs;
        this.panel1.Paint += panel1_Paint;
    }

does not work neither.

        private void panel1_Paint(object sender,AnglePaintEventArgs e)

Is it necessary to derive a new panel object class? Does it help to declare a new delagate with the AnglePaintEventArgs and hook it to the panel object?


Solution

  • This strikes me as a bit of an X-Y Problem because even if you were to succeed in injecting an angle into a custom PaintEventArgs class a line and draw it, it's likely to be erased on the next refresh unless you're persisting it in a document of some kind. Same goes for a Tag. To draw on any control, call its Refresh() method and it will respond by firing the Paint message and providing a Graphics blank canvas to draw on. Given that the effect of having an angle property in the event argument or a tag would be so ephemeral, it's not a good fit there.

    Consider making a Line class with the Angle property that goes in a List<object> that can hold the various shapes you want to draw. You can continue to add more lines to the document, then call pictureBox.Refresh whenever there is a new shape to draw.

    lines with angles

    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
                    pictureBox.Paint += (sender, e) =>
            {
                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
                foreach (var shape in Document)
                {
                    if(shape is Line line)
                    {                    
                        using (var pen = new Pen(Color.White, line.Width))
                        {
                            e.Graphics.DrawLine(pen, line.Origin, line.EndPoint);
                        }
                    }
                }
            };
            for (double angle = 0; angle<360; angle += 15)
            {
                Document.Add(new Line
                {
                    Origin = pictureBox.GetCenterPoint(),
                    Angle = angle,
                    Length = 150,
                });
            }
        }
        List<object> Document { get; } = new List<object>();
    }
    

    class Line
    {
        public Point Origin { get; set; }
        public double Angle { get; set; }
        public double Length { get; set; }
        public Point EndPoint
        {
            get
            {
                double radians = Angle * Math.PI / 180;
                int endX = (int)(Origin.X + Length * Math.Cos(radians));
                int endY = (int)(Origin.Y + Length * Math.Sin(radians));
                return new Point(endX, endY);
            }
        }
        public float Width { get; set; } = 2f;
    }
    

    Extensions

    static partial class Extensions
    {
        public static Point GetCenterPoint(this Control control) =>
            new Point(
                control.ClientRectangle.Left + control.ClientRectangle.Width / 2,
                control.ClientRectangle.Top + control.ClientRectangle.Height / 2);
    }