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

本文关键字:图像 缓冲 旋转 图形 | 更新日期: 2023-09-27 17:53:31

我正在尝试将可移动的针(指针)放在量规(仪表)的固定图形上。通过在缓冲图形上使用矩阵旋转来移动指针。我可以得到固定图形和针显示。但是当我渲染到屏幕上时,最后放置的图像删除了先前的图形。我使用计时器来获得针动画和跟踪条输入来产生运动。这针的运动正好符合我的要求。

我就是不能让固定背景和指针同时出现。

任何想法?

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)
        {

        }
    }
}

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

你所采用的一般图形方法不适用于winforms应用程序。

图形在winforms中的工作方式,每当窗体被覆盖/覆盖/调整大小等,Windows告诉它重新绘制自己。你对CreateGraphics所做的任何事情都将在此时被覆盖。这就是为什么你不应该调用CreateGraphics

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

这是"正确方式"的大致形状:

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