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

C# WinForms开启双缓冲后面板滑出动画失效问题咨询

问题原因

  • 核心逻辑错误:你在Timer.Tick事件回调中使用do...while循环一次性将面板高度调整到了目标值,WinForm的UI重绘是在UI线程的消息队列空闲时执行的,同步执行的高度调整逻辑全部运行完成后才会触发一次重绘,相当于整个动画只有1帧,自然看不到渐变效果。
  • 你观察到的滑入正常属于偶发现象,和双缓冲开启后重绘机制的优化有关,双缓冲本身不会导致动画异常。

修复方案

每次Timer.Tick触发时仅调整一次面板高度,到达目标值后再停止计时器即可,修正后的代码如下:

public partial class Form1 : Form
{
    private const int MaxHeight = 137;
    private const int MinHeight = 0;
    private readonly Timer _timer1 = new Timer { Interval = 30 };
    private bool _isExpanding;

    public Form1()
    {
        InitializeComponent();
        _timer1.Tick += Timer1_Tick;
        // 可选:给Panel开启双缓冲避免闪烁
        typeof(Panel).InvokeMember("DoubleBuffered",
            System.Reflection.BindingFlags.SetProperty | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic,
            null, panel1, new object[] { true });
    }

    private void Timer1_Tick(object sender, EventArgs e)
    {
        if (_isExpanding)
        {
            panel1.Height = Math.Min(panel1.Height + 3, MaxHeight);
            if (panel1.Height == MaxHeight)
            {
                _timer1.Stop();
            }
        }
        else
        {
            panel1.Height = Math.Max(panel1.Height - 3, MinHeight);
            if (panel1.Height == MinHeight)
            {
                _timer1.Stop();
            }
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        _isExpanding = panel1.Height == MinHeight;
        _timer1.Start();
    }
}

优化说明

  • 将计时器间隔调整为30ms,每次调整高度步长设为3,既保证了动画流畅度,也不会占用过多UI线程资源。
  • 新增_isExpanding字段标记动画方向,避免高度调整逻辑判断出错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:54:04