繁体   English   中英

在具有透明度的情况下使用Graphics.DrawImage时C#闪烁

[英]C# flickering when using Graphics.DrawImage with Transparancy

使用graphics.Drawimage绘制特定的动画GIF图像时出现闪烁问题。 我已经编写了一个小程序,其中包含我程序中的代码片段,以准确显示我要完成的工作,即直接在桌面上显示透明的动画图像,并接受事件处理程序,例如鼠标单击。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;

namespace Transparancy_Example
{
    class TransparentForm : System.Windows.Forms.Form
    {
        public TransparentForm()
    {
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        UpdateStyles();
        this.TopMost = true;
        this.FormBorderStyle = FormBorderStyle.None;
        this.ShowInTaskbar = false;
        this.AllowTransparency = true;
        this.StartPosition = FormStartPosition.CenterScreen;
        TransparentControl tc = new TransparentControl();
        tc.Parent = this;
        tc.Dock = DockStyle.Fill;
        tc.BackColor = Color.Transparent;
        tc.Image = Properties.Resources.animated_gif;
        this.Controls.Add(tc);
        this.Size = tc.Image.Size;
        this.SetBounds(0, 0, Width, Height);
        Bitmap bmp = new Bitmap(tc.Image);
        Color makeColorTransparent = bmp.GetPixel(0, 0);
        if (bmp.PixelFormat != PixelFormat.Format32bppArgb && makeColorTransparent.A != Color.Transparent.A)
        {
            this.TransparencyKey = bmp.GetPixel(0, 0);
        }
        else if (makeColorTransparent.A != Color.Transparent.A)
        {
            this.TransparencyKey = bmp.GetPixel(0, 0);
        }
        else
        {
            this.TransparencyKey = this.BackColor;
        }
    }
}
public class TransparentControl : Control
{
    private readonly Timer refresher;
    private Image _image;

    public TransparentControl()
    {
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        UpdateStyles();

        BackColor = Color.Transparent;
        refresher = new Timer();
        refresher.Tick += TimerOnTick;
        refresher.Interval = 50;
        refresher.Enabled = true;
        refresher.Start();
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x020;
            return cp;
        }
    }

    protected override void OnMove(EventArgs e)
    {
        RecreateHandle();

    }

    protected override void OnPaint(PaintEventArgs e)
    {
        if (_image != null)
        {

            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            double ratioX = (double)Width / (double)_image.Width;
            double ratioY = (double)Height / (double)_image.Height;
            double ratio = ratioX < ratioY ? ratioX : ratioY;
            int newHeight = Convert.ToInt32((double)_image.Height * ratio);
            int newWidth = Convert.ToInt32((double)_image.Width * ratio);
            int posX = Convert.ToInt32((Width - ((double)_image.Width * ratio)) / 2);
            int posY = Convert.ToInt32((Height - ((double)_image.Height * ratio)) / 2);

            e.Graphics.DrawImage(_image, posX, posY, newWidth, newHeight);
            ImageAnimator.UpdateFrames(_image);

        }
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        //Do not paint background
    }

    public void Redraw()
    {
        RecreateHandle();
    }

    private void TimerOnTick(object source, EventArgs e)
    {
        RecreateHandle();
        refresher.Stop();
        ImageAnimator.Animate(_image, onFrameChangedHandler);

    }

    private void onFrameChangedHandler(object sender, EventArgs e)
    {
        if (Parent != null)
        {
            this.Parent.Invalidate(this.Bounds, false);
        }
    }

    public Image Image
    {
        get
        {
            return _image;
        }
        set
        {
            _image = value;
            RecreateHandle();
        }
    }
}
}

一切似乎都很好,但是如果我尝试添加任何双缓冲,则会出现很多问题。

我设法找到了自己的问题的答案。

我添加了this.DoubleBuffered = true; 到TransparentForm并添加公共重写,如下所示:

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x02000000;
            return cp;
        }
    }

不要问我为什么0x0200x0200不起作用,但是那会覆盖CreateParams和带有TransparentControl双缓冲区的CreateParams,并且不会让图像闪烁并保持所有透明度。

在此处找到此解决方案: 如何解决用户控件中的闪烁

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM