You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# VS2019 Windows Form开启AutoScroll属性后滚动闪烁问题求助

问题成因

你遇到的滚动闪烁是WinForm场景下的常见问题,核心原因有两个:

  1. 窗体默认未开启针对滚动场景优化的双缓冲机制,滚动时窗体会先擦除背景再重绘所有可见控件,多次交替绘制就会产生闪烁感
  2. 你在循环中逐个将控件添加到窗体,每次添加都会触发布局重绘,额外增加了绘制开销,也会加剧滚动时的卡顿闪烁

修复方案

按下面的步骤修改代码即可解决问题:

  1. 给动态生成的allShows窗体开启双缓冲,同时开启复合绘制优化
  2. 控件批量添加前挂起窗体布局,全部添加完成后再恢复布局,减少不必要的重绘
  3. 可选优化:如果你的数据量较大,建议优先用FlowLayoutPanel或者自定义绘制的列表控件替代手动生成大量独立控件,性能会更好

修改后的完整代码

private void allShowsToolStripMenuItem_Click(object sender, EventArgs e)
{
    try
    {
        // 从数据库加载所有节目数据
        DataTable dt = accesse.LoadAllShows();

        // 创建展示页面窗体
        Form allShows = new Form();

        // ========== 新增:开启窗体双缓冲优化 ==========
        typeof(Form).InvokeMember(
            "DoubleBuffered", 
            System.Reflection.BindingFlags.SetProperty | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, 
            null, 
            allShows, 
            new object[] { true }
        );
        allShows.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
        allShows.UpdateStyles();

        // 初始化控件数组
        PictureBox[] pic = new PictureBox[dt.Rows.Count];
        Label[] showName = new Label[dt.Rows.Count], season = new Label[dt.Rows.Count], eps = new Label[dt.Rows.Count], typ = new Label[dt.Rows.Count];
        TextBox[] txtShowName = new TextBox[dt.Rows.Count], txtSeason = new TextBox[dt.Rows.Count], txtEps = new TextBox[dt.Rows.Count], txtTyp = new TextBox[dt.Rows.Count];

        // 窗体基础属性配置
        allShows.BackColor = Color.White;
        allShows.Font = new Font("Calibri", 14f, FontStyle.Regular);
        allShows.ForeColor = Color.Black;
        allShows.Size = new Size(1050, 700);
        allShows.StartPosition = FormStartPosition.CenterScreen;
        allShows.AutoScroll = true;
        allShows.AutoScrollMargin = new Size(0, 18);
        

        // 布局计算变量
        int y = 325; // 控件垂直间距
        bool xTurn = false; // 左右列切换标识
        int yTurnNum = 0; // 行号计数

        // ========== 新增:添加控件前挂起布局 ==========
        allShows.SuspendLayout();

        for (int i = 0; i < dt.Rows.Count; i++)
        {
            // 海报图控件配置
            pic[i] = new PictureBox();
            pic[i].BorderStyle = BorderStyle.FixedSingle;
            pic[i].Size = new Size(162, 288);
            pic[i].SizeMode = PictureBoxSizeMode.StretchImage;
            pic[i].Image = Image.FromFile(dt.Rows[i][4].ToString());

            // 节目名称标签配置
            showName[i] = new Label();
            showName[i].Text = "节目名称: " + dt.Rows[i][0];
            showName[i].AutoSize = true;

            // 季数标签配置
            season[i] = new Label();
            season[i].Text = "季数: " + dt.Rows[i][1];
            season[i].AutoSize = true;

            // 集数标签配置
            eps[i] = new Label();
            eps[i].Text = "集数: " + dt.Rows[i][2];
            eps[i].AutoSize = true;

            // 类型标签配置
            typ[i] = new Label();
            typ[i].Text = "类型: " + dt.Rows[i][3];
            typ[i].AutoSize = true;

            if (xTurn)
            {
                // 右列控件位置计算
                pic[i].Location = new Point(515, pic[i - 1].Location.Y);
                showName[i].Location = new Point(687, showName[i - 1].Location.Y);
                season[i].Location = new Point(687, season[i - 1].Location.Y);
                eps[i].Location = new Point(687, eps[i - 1].Location.Y);
                typ[i].Location = new Point(687, typ[i - 1].Location.Y);

                xTurn = false;
            }
            else
            {
                // 左列控件位置计算
                pic[i].Location = new Point(15, 15 + (yTurnNum * y));
                showName[i].Location = new Point(187, 20 + (yTurnNum * y));
                season[i].Location = new Point(187, 55 + (yTurnNum * y));
                eps[i].Location = new Point(187, 90 + (yTurnNum * y));
                typ[i].Location = new Point(187, 125 + (yTurnNum * y));

                yTurnNum += 1;
                xTurn = true;
            }

            // 把控件添加到窗体
            allShows.Controls.Add(pic[i]);
            allShows.Controls.Add(showName[i]);
            allShows.Controls.Add(season[i]);
            allShows.Controls.Add(eps[i]);
            allShows.Controls.Add(typ[i]);
        }

        // ========== 新增:所有控件添加完成后恢复布局 ==========
        allShows.ResumeLayout(false);
        allShows.PerformLayout();

        allShows.ShowDialog();
    }
    catch (Exception ex)
    {
        tools.ShowErrorMessageBox(ex.Message, "错误");
    }
}

如果以上修改后还是有轻微闪烁,你可以自定义一个继承自Form的子类,在构造函数中提前设置好所有绘制优化参数,再用这个子类创建你的allShows窗体即可。


内容的提问来源于stack exchange,提问作者TheDarkAbyss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 05:27:03