C#WinForms - DrawImage而不会丢失动画

时间:2011-11-28 07:39:24

标签: c# graphics

如何DrawImage不丢失动画?

        pictureBox1.Image = new Bitmap(20, 20);
        Graphics g = Graphics.FromImage(pictureBox1.Image);
        Image i = Properties.Resources.SuperMario; //Animated GIF; sprite; 20px X 20px
        g.DrawImage(i, 
            new Rectangle(0, 0, 20, 20),
            new Rectangle(0, 0, 20, 20),
            GraphicsUnit.Pixel);
        pictureBox1.Refresh();

以上代码,将动画精灵表(GIF格式)中的图像部分复制到PictureBox'Image。不幸的是,动画丢失了。

这是精灵表:http://www.google.com/imgres?q=sprite+20x20&um=1&hl=en&client=firefox-a&rls=org.mozilla:en-US:official&biw=1067&bih=671&tbm=isch&tbnid=ulN4JRy6N4ToSM:&imgrefurl=http://nkelsch.deviantart.com/art/Super-Mario-20x20-Sprites-83482505&docid=GOCF1PgjPytbPM&imgurl=http://www.deviantart.com/download/83482505/Super_Mario_20x20_Sprites_by_nkelsch.gif&w=251&h=356&ei=4orQTvXPIKePiAerio24Dg&zoom=1&iact=hc&vpx=89&vpy=154&dur=7579&hovh=267&hovw=188&tx=131&ty=137&sig=107474527571502851152&page=1&tbnh=122&tbnw=86&start=0&ndsp=18&ved=1t:429,r:0,s:0

提前谢谢。

5 个答案:

答案 0 :(得分:1)

您必须使用某种计时器/线程以正确的动画速率不断更新图像。 graphics.drawImage只在调用时绘制一次图像,它不理解动画。

如果你真的想使用这种动画方法,你应该保留一个变量来保存帧索引。删除表单上的Timer组件,并将其设置为以动画制作动画的间隔触发。当计时器触发增加帧计数器时,然后清除,并使用新索引的帧边界重绘图片框。当它超出动画中的最大帧时,你应该将帧计数器包装回0。

答案 1 :(得分:1)

将整个gif加载到图片框中并将其定位,使得只有相关部分显示在图片框中。多数精灵是如何运作的。您不必复制特定帧的部分,因为是,这显然会丢失动画。

将图片框放在面板中,然后将图片框的位置设置为精灵元素的位置。

答案 2 :(得分:1)

PictureBox天生就能理解动画GIF。

为什么需要在Update方法中手动绘制它?

创建PictureBox就足够了,将动画GIF设置为Image的{​​{1}}。

还要确保您不在GUI线程上运行任何阻止代码,因为这将阻止动画运行。

答案 3 :(得分:1)

您可以访问该链接获取源代码http://www.codeproject.com/KB/GDI-plus/NGif.aspx

答案 4 :(得分:1)

    class WinForm : Form
    {
        bool FrameLoop = false;
        int FrameIndex = 0;
        int FrameCount = 0;
        FrameDimension FrameDimension = null;
        List<int> DelayTime = new List<int>();
        Image img;

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            this.DoubleBuffered = true;
            img = Image.FromFile("C:\\debug.gif");
            if (img.FrameDimensionsList != null)
                foreach (Guid i in img.FrameDimensionsList)
                {
                    FrameDimension = new FrameDimension(i);
                    FrameCount = img.GetFrameCount(FrameDimension);
                }
            if (FrameCount > 1)
            {
                foreach (PropertyItem i in img.PropertyItems)
                {
                    if (i.Id == 0x5100)
                    {
                        for (int j = 0; j < FrameCount; j++)
                        {
                            DelayTime.Add(BitConverter.ToInt32(i.Value, j * 4));
                        }
                    }
                    else if (i.Id == 0x5101)
                    {
                        FrameLoop = true;
                    }
                }
                this.BeginInvoke(new EventHandler(Animation));
            }
        }

        private void Animation(object sender,EventArgs e)
        {
            img.SelectActiveFrame(FrameDimension, FrameIndex);
            this.Refresh();
            Application.DoEvents();
            Thread.Sleep(DelayTime[FrameIndex] * 10);

            FrameIndex++;
            if (FrameIndex >= FrameCount)
            {
                if (FrameLoop)
                    FrameIndex = 0;
                else
                    return;
            }
            Animation(sender, e);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (img == null)
                return;
            e.Graphics.DrawImage(img, new Point(0, 0));
            //base.OnPaint(e);
        }
    }