将缓冲矩阵旋转图形放置在固定图像上

时间:2016-06-30 23:55:51

标签: c# graphics

我试图将可移动的针(指针)放在仪表(仪表)的固定图形上。通过在缓冲图形上使用矩阵旋转来移动针。我可以得到固定的图形和针头显示。但是当我渲染到屏幕时,最后放置的图像会删除先前的图形。我正在使用计时器来获取针动画和轨迹栏输入以产生运动。针做了我正在寻找的确切运动。

我无法让固定的背景和针头同时出现。

有什么想法吗?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Dial01
{
    public partial class dial01Form : Form
    {
        // Establishes timer for graphics animation

        private Timer timer01 = new Timer();

        /* Establishes a graphic buffer to write to 
         * prior display on screen */

        private Graphics myGraphics;
        private BufferedGraphics myBufferedGraphics1;

        // Establishes manager for embedded resources (Images)
        private System.Resources.ResourceManager myRM = new
            System.Resources.ResourceManager("Resources.resx", 
            System.Reflection.Assembly.GetExecutingAssembly());

        int y = 0;      // Rotation value
        Graphics g,g1;     // Graphics objects

        public dial01Form()
        {
            // Establishes size of Dial01Form
            this.Width = 500;
            this.Height = 500;

            // Gets reference to the current BufferedGraphicsContext
            BufferedGraphicsContext myContext1 = BufferedGraphicsManager.Current;

            // Specifically sets maximum buffer size
            myContext1.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);

            // Sets the buffer size
            myBufferedGraphics1 = myContext1.Allocate(this.CreateGraphics(),
               new Rectangle(0, 0, this.Width, this.Height));


            // Actvates timer and sets interval
            timer01.Enabled = true;
            timer01.Tick += onTimer;
            timer01.Interval = 20;
            timer01.Start();

            // Initializes form components
            InitializeComponent();
        }

        private void onTimer(object sender, System.EventArgs e)
        {
            myGraphics = this.CreateGraphics();

            //  Initializes graphics buffer variable
            g1 = myBufferedGraphics1.Graphics;

            // Clears graphic buffer with a color
            g1.Clear(SystemColors.Control);


            // Initializes an image variable for Dial Outline
            Image dial01Outline = Dial01.Properties.Resources.DialOutline250x250;

            // Draw Dial Outline to graphics buffer
            myGraphics.DrawImage(dial01Outline, (ClientSize.Width / 2) - 100, 
                (ClientSize.Height / 2) - 100);

            // Goto drawPointer method passing trackBar1 value
            drawPointer(trackBar1.Value);


            // Render buffered graphics to screen
            // myBufferedGraphics.Render(Graphics.FromHwnd(this.Handle));
            myBufferedGraphics1.Render();          

        }

        public int drawPointer(int trkBarValue)
        {
            int x = trkBarValue;
            y = 0;
            if (225 + x <= 360) { y = 222 + x; }
            else if (225 + x > 360) { y = x - 135; }

            // These two labels are for testing purposes
            label1.Text = ("Trk Bar Val = " + x).ToString();
            label2.Text = ("Ptr value   = " + y).ToString();           

            y = y + 180;

            // Matrix rotation to pointer          
            Matrix myMatrix = new Matrix();
            myMatrix.Rotate(y, MatrixOrder.Append);
            myMatrix.Translate(this.ClientSize.Width / 2,
                this.ClientSize.Height / 2, MatrixOrder.Append);
            g1.Transform = myMatrix;


            // Pointer polygon
            PointF point1 = new PointF(0.0F, 0.0F);
            PointF point2 = new PointF(0.0F, 50.0F);
            PointF point3 = new PointF(3.0F, 55.0F);
            PointF point4 = new PointF(7.0F, 50.0F);
            PointF point5 = new PointF(7.0F, 0.0F);

            PointF[] polyPoints =
            {
                 point1,
                 point2,
                 point3,
                 point4,
                 point5
            };

            g1.FillPolygon(Brushes.Black, polyPoints);


            return y;
        }


        private void dial01Form_Load(object sender, EventArgs e)
        {

        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {


        }
    }
}

1 个答案:

答案 0 :(得分:1)

您采用的一般图形方法不适用于winforms应用。

图形在winforms中的工作方式,只要窗体被覆盖/未覆盖/调整大小/等,Windows就会让它重新绘制自己。您在CreateGraphics完成的任何操作都将被覆盖。这就是你不应该致电CreateGraphics的原因。

相反,您应该通过Paint事件拦截重新绘制过程,并在那里进行所有自定义绘制。您仍然可以在计时器上重新绘制,只需在计时器内调用Invalidate(),这会导致表单尽快重新绘制。

这是&#34;正确方式的一般形状&#34;这样做:

public partial class dial01Form : Form
{
    private Timer timer01 = new Timer();

    int y = 0;      // Rotation value

    public dial01Form()
    {
        // Establishes size of Dial01Form
        this.Width = 500;
        this.Height = 500;

        // Actvates timer and sets interval
        timer01.Enabled = true;
        timer01.Tick += onTimer;
        timer01.Interval = 20;
        timer01.Start();

        // handle the paint event
        this.Paint += OnPaint;

        // Initializes form components
        InitializeComponent();
    }

    private void OnPaint(object sender, PaintEventArgs e)
    { 
        // all painting here, targeting e.Graphics
        e.Graphics.Clear(SystemColors.Control);
        Image dial01Outline = Dial01.Properties.Resources.DialOutline250x250;
        e.Graphics.DrawImage(dial01Outline, (ClientSize.Width / 2) - 100, 
            (ClientSize.Height / 2) - 100);
        drawPointer(e.Graphics, trackBar1.Value);
    }

    private void onTimer(object sender, System.EventArgs e)
    {
        this.Invalidate();
    }

    public int drawPointer(Graphics g1, int trkBarValue)
    {
        // elided: same code as before, but using the g1 parameter instead of a field
    }

}

我认为你不应该遇到闪烁问题 - 默认情况下启用双缓冲。确保您的表单DoubleBuffered属性设置为True。