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

带自定义绘制控件的Panel滚动时绘制异常问题求助

解决Panel滚动时自定义控件绘制异常的问题

嘿,我帮你找到这个滚动绘制问题的症结啦!你遇到的向左滚动时控件显示异常的情况,核心问题出在自定义控件的OnPaint方法里对绘制区域的处理上。

问题根源

你在OnPaint里用了pe.ClipRectangle.X和pe.ClipRectangle.Y来创建椭圆的绘制矩形,但ClipRectangle是相对于当前控件自身的客户端坐标,不是Panel滚动后的全局偏移坐标。当向左滚动时,Panel的AutoScrollPosition会改变控件的显示偏移,但你的绘制代码错误地把ClipRectangle的起始坐标当成了绘制起点,导致椭圆的位置跑偏,自然就显示异常了。

解决方案

修改自定义控件的OnPaint方法,直接基于控件自身的内部坐标来绘制(比如从(0,0)开始),Panel的滚动偏移会由WinForms自动处理,完全不需要你手动调整绘制位置。另外还可以优化一下滚动逻辑,去掉不必要的手动重绘调用。

修改后的自定义控件代码

public partial class CustomControl1 : Control
{
    public bool isOdd { get; set; }

    public CustomControl1()
    {
        InitializeComponent();
        // 开启双缓冲,减少滚动时的控件闪烁
        this.DoubleBuffered = true;
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        Graphics gr = pe.Graphics;
        // 直接使用控件自身的客户端区域作为绘制范围
        Rectangle rc = new Rectangle(0, 0, this.ClientSize.Width, this.ClientSize.Height);
        // 简化Brush的赋值逻辑
        Brush br = isOdd ? new SolidBrush(Color.Yellow) : new SolidBrush(Color.Red);
        
        gr.FillEllipse(br, rc);
        base.OnPaint(pe);
        // 记得释放Brush资源,避免内存泄漏
        br.Dispose();
    }

    protected override void OnPaintBackground(PaintEventArgs pe)
    {
        base.OnPaintBackground(pe);
    }
}

优化后的Form滚动逻辑

原来的滚动代码有两处小问题:左滚动的边界判断不准确,右滚动时错误引用了垂直滚动的最大值,而且手动调用Invalidate完全没必要——WinForms会自动处理滚动后的控件重绘。修改后的代码如下:

private void keyPress(object sender, KeyEventArgs e)
{
    switch (e.KeyCode)
    {
        case Keys.A:
            if (location - 20 >= 0)
            {
                location -= 20;
                pn.HorizontalScroll.Value = location;
            }
            else
            {
                location = 0;
                pn.AutoScrollPosition = new Point(location, 0);
            }
            break;
        case Keys.D:
            if (location + 20 <= pn.HorizontalScroll.Maximum)
            {
                location += 20;
                pn.HorizontalScroll.Value = location;
            }
            else
            {
                location = pn.HorizontalScroll.Maximum;
                pn.AutoScrollPosition = new Point(location, 0);
            }
            break;
    }
    // 移除不必要的手动重绘调用
    // foreach(Control c in pn.Controls) { c.Invalidate(); }
}

效果验证

这样修改之后,不管你向左还是向右滚动Panel,自定义控件都会基于自身的内部坐标正确绘制椭圆,WinForms会自动处理滚动带来的偏移,再也不会出现绘制异常的情况了。开启双缓冲还能让滚动过程更流畅,减少闪烁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:51:58