c#使用图形时闪烁.使用透明绘制图像

本文关键字:绘制 图像 透明 图形 闪烁 | 更新日期: 2023-09-27 18:01:40

我在使用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();
        }
    }
}
}

一切看起来都很好,但是如果我尝试添加任何doublebuffering,就会出现很多问题。

c#使用图形时闪烁.使用透明绘制图像

我终于找到了自己问题的答案。

我将this.DoubleBuffered = true;添加到TransparentForm中,并添加了如下的公共覆盖:

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

不要问我为什么0x0200x0200不工作,但覆盖CreateParams与CreateParams与TransparentControl双缓冲区相结合,不让图像闪烁并保持所有透明度。

如何修复用户控件
中的闪烁问题