我的 C# 表单闪烁,我无法修复它。我已经尝试了一切

Posted

技术标签:

【中文标题】我的 C# 表单闪烁,我无法修复它。我已经尝试了一切【英文标题】:My C# form flickers and I can't fix it. I've tried everything 【发布时间】:2021-10-10 21:48:21 【问题描述】:

我已经在这个程序上工作了大约一个月,尝试了一切。无论我做什么,我的程序都会闪烁,即使在其他机器上也是如此。它只是一个背景、一个图像和一个矩形。没有什么大的或昂贵的。然而它仍然闪烁。我尝试将 DoubleBuffered 设置为 true,我尝试了覆盖 CreateParams(它使我的窗口变黑),我尝试使用一种方法进行反射,我尝试使用 SetStyle 来设置 DoubleBuffer、OptimedDoubleBuffer、UserPaint、AllPaintingInWmPain 和 Opaque当设置为 true 时,它​​们都没有做任何事情。我已经搜索了谷歌和 *** 的答案,但它们都不起作用。我不明白我做错了什么。我添加了代码、exe、编译脚本和图像的 zip。我和其他人的计算机上发生的事情就是 gif 上的内容。该程序每秒更新 4 次,足以绘制背景、图像和正方形,但它仍然闪烁。请问我需要帮助。

Main.cs:

using System;
using System.Threading;
using System.Windows.Forms;

public class main

    public static void Main(string[] args)
    
        Console.WriteLine("START");
    
        Engine.Init();
    
        while(true)
        
            Engine.MainDraw();
            Application.DoEvents();
        
            Thread.Sleep(250);
        
    
        Console.WriteLine("END");
    
    


Engine.cs:

using System;
using System.IO;
using System.Windows;
using System.Windows.Forms;
using System.Drawing;

public class Engine : Form
    
    public static Engine EngineForm = new Engine();
    public static Graphics g;
    
    /*
    protected override CreateParams CreateParams
        get
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x02000000;
            return cp;
        
    
    //*/
    
    /*
    public static void enableDoubleBuff(System.Windows.Forms.Control cont)
        System.Reflection.PropertyInfo DemoProp = typeof(System.Windows.Forms.Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        DemoProp.SetValue(cont, true, null);
    
    //*/
    
    public Engine()
        
        this.DoubleBuffered = true;
        
        //enableDoubleBuff(this);
        
        this.SetStyle(
            ControlStyles.DoubleBuffer |
            ControlStyles.OptimizedDoubleBuffer |
            ControlStyles.UserPaint |
            ControlStyles.AllPaintingInWmPaint |
            ControlStyles.Opaque
            ,
        true);
        this.UpdateStyles();
    
    
    public static void Init()
        EngineForm.Enabled = true;
        EngineForm.Visible = true;
        
        EngineForm.Activate();
        
        g = EngineForm.CreateGraphics();
    
    
    public static Pen pen = new Pen(Color.FromArgb(255, 0, 0, 0), 5);
    
    public static Image image = Image.FromFile("bulbasaur.png");
    
    public static Color color = Color.FromArgb(200, 200, 255, 255);
    
    public static void MainDraw()
        g.Clear(color);
        
        g.DrawImage(image, new PointF(0, 0));
        
        g.DrawRectangle(pen, 100, 100, 100, 100);
    
    

程序的样子:

【问题讨论】:

当你省略 g.Clear(color); 时会是什么样子? 这个:g = EngineForm.CreateGraphics(); 可能是你能做的最糟糕的事情。其余的在Main。像往常一样运行你的表单,覆盖它的OnPaint() 方法,在那里绘制你的东西,使用 PaintEventArgs 提供的图形对象(如果你想要双缓冲工作)——没有循环,这不是一个控制台应用程序(你的代码对待它喜欢一个)。 -- 仅设置 ControlStyles.OptimizedDoubleBufferDoubleBuffered = true 。为什么ControlStyles.Opaque?你想用这个做什么?为什么要尝试单例?仍然潜伏着控制台的东西吗? 【参考方案1】:

您看到的问题是因为CreateGraphics 创建了一个绕过双缓冲的Graphics 实例,使您可以直接访问窗口的画布。无论您对 Graphics 对象做什么,都会立即在屏幕上发生。

要解决此问题,您需要覆盖在正常更新过程中调用的表单方法之一:OnPaintOnPaintBackground。这些接收一个Graphics 对象,它将按照您的意愿工作,包括处理双缓冲:

protected override void OnPaintBackground(PaintEventArgs e)

    base.OnPaintBackground(e);
    var g = e.Graphics;
    g.Clear(color);
    g.DrawImage(image, 0, 0);
    g.DrawRectangle(pen, 100, 100, 100, 100);

每当窗体被重绘、控件被绘制之前等时都会调用它。您可以通过调用Invalidate() 来重绘窗体:

public static void MainDraw()

    EngineForm.Invalidate();

这会向窗口发布一条消息,告诉它重绘。下一次通过事件循环将处理该消息并调用 OnPaintBackground()

结果是平滑、无闪烁的更新。您可以在没有Clear 导致背景闪烁等情况下制作动画和其他内容。

【讨论】:

非常感谢。我不知道图形会是这样的。有效。谢谢你,我花了这么多时间在这上面,但它从来没有用过谢谢谢谢谢谢

以上是关于我的 C# 表单闪烁,我无法修复它。我已经尝试了一切的主要内容,如果未能解决你的问题,请参考以下文章

无法修复 React 暗模式闪烁

我的网站上的 PHP 联系表单错误。 PHP 新手,但我发誓这之前有效并且停止了,我无法弄清楚如何修复它 [重复]

C# 方法通过字符串动态生成表单

无法在运行时以编程方式影响闪烁控制

visual c# 表单更新导致闪烁

如何解决 C# 中的简单变量问题?