使用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();
}
}
}
}
一切似乎都很好,但如果我尝试添加任何双重缓冲,就会出现很多问题。
答案 0 :(得分:1)
我设法找到了自己问题的答案。
我将this.DoubleBuffered = true;
添加到TransparentForm并添加了公共覆盖,如下所示:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
不要问我为什么0x020
或0x0200
不起作用,而是覆盖CreateParams与CreateParams结合使用TransparentControl双缓冲区,并且不会让图像闪烁并保持所有透明度。
此解决方案可在此处找到:How to fix the flickering in User controls