我有一个填充父表格的面板
我使用计时器来捕获屏幕,
并定期将屏幕截图设置为Panel的背景图片。
然而,它会遇到疯狂的闪烁。我能做些什么来解决它?
//Part of code
public partial class Form1 : Form
{
DxScreenCapture sc = new DxScreenCapture();
public Form1()
{
InitializeComponent();
panelMain.BackgroundImageLayout = ImageLayout.Zoom;
}
private void Form1_Load(object sender, EventArgs e)
{
}
void RefreshScreen()
{
Surface s = sc.CaptureScreen();
DataStream ds = Surface.ToStream(s, ImageFileFormat.Bmp);
panelMain.BackgroundImage = Image.FromStream(ds);
s.Dispose();
}
private void timer1_Tick(object sender, EventArgs e)
{
RefreshScreen();
}
}
答案 0 :(得分:7)
尝试使用双缓冲面板。继承面板,将DoubleBuffered设置为true并使用该面板而不是默认面板:
namespace XXX
{
/// <summary>
/// A panel which redraws its surface using a secondary buffer to reduce or prevent flicker.
/// </summary>
public class PanelDoubleBuffered : System.Windows.Forms.Panel
{
public PanelDoubleBuffered()
: base()
{
this.DoubleBuffered = true;
}
}
}
修改强>
此外,我想鼓励您更多地关注您使用的资源。每当一个对象实现IDisposable接口时 - 在不再需要时处置该对象。在处理非托管资源(例如流!)时,这非常重要。
void RefreshScreen()
{
using (Surface s = sc.CaptureScreen())
{
using (DataStream ds = Surface.ToStream(s, ImageFileFormat.Bmp))
{
Image oldBgImage = panelMain.BackgroundImage;
panelMain.BackgroundImage = Image.FromStream(ds);
if (oldBgImage != null)
oldBgImage.Dispose();
}
}
}
答案 1 :(得分:3)
在Visual Studio中实际上有一个不需要代码的简单解决方案!
如果您转到解决方案资源管理器,然后双击您的表单( Form1 ),则会弹出一个列表(如果它没有弹出您必须右键单击表单并转到属性并再次双击)。然后,转到 DoubleBuffered 并将其更改为 True 。
答案 2 :(得分:2)
我自己从其他网站找到答案。它在面板上设置了一些 ControlStyles ,如下面的代码所示。并且不再闪烁。
class SomePanel : Panel
{
public SomePanel()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
}