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

WinForm自定义绘制ListBox条目时频繁闪烁卡顿问题求解

问题根因

你当前遇到的卡顿闪烁完全由DrawItem事件的不合理逻辑导致:

  • 绘制单条ListBox条目时,重复调用Excel COM接口读取B1:B20范围,Excel交互本身耗时极高,且该操作会在ListBox每次重绘时被触发数百上千次
  • 多余的20次循环逻辑会让同一个条目文字被重复绘制20次,完全属于无效操作
  • 仅开启窗体双缓冲不生效,因为ListBox控件本身默认未开启双缓冲,且你逻辑的性能问题远大于绘制本身的闪烁问题

优化方案

第一步:提前缓存Excel数据

不要在绘制事件中操作Excel,在窗体加载、ListBox绑定数据的阶段一次性读取B列的数量值,存储到本地集合:

' 窗体级别变量,存储B列数量缓存
Dim ItemCountCache As New List(Of Integer)()

' 放在你填充ListBox的逻辑后面,一次性读取Excel数据
DataRange = WS.Range("B1:B20")
ItemCountCache.Clear()
For Each cell In DataRange
    ItemCountCache.Add(CInt(cell.Value))
Next

第二步:修复DrawItem逻辑

删除多余循环,直接读取对应索引的缓存判断颜色:

Private Sub P_List_LB_DrawItem(sender As Object, e As System.Windows.Forms.DrawItemEventArgs) Handles P_List_LB.DrawItem
    e.DrawBackground()
    
    ' 边界判断,避免索引溢出
    If e.Index < 0 OrElse e.Index >= P_List_LB.Items.Count OrElse e.Index >= ItemCountCache.Count Then
        Exit Sub
    End If
    
    ' 直接读缓存判断颜色,不需要循环、不需要操作Excel
    Dim brush = If(ItemCountCache(e.Index) > 0, Brushes.Black, Brushes.Gray)
    e.Graphics.DrawString(P_List_LB.Items(e.Index).ToString(), e.Font, brush, e.Bounds.Location)
    
    ' 补充绘制焦点框,避免选中状态显示异常
    e.DrawFocusRectangle()
End Sub

第三步:给ListBox开启双缓冲(可选,进一步优化闪烁)

在窗体构造函数或者Load事件中添加以下代码,通过反射开启ListBox的双缓冲:

Dim flag As System.Reflection.BindingFlags = System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance
Dim method As System.Reflection.MethodInfo = GetType(Control).GetMethod("SetStyle", flag)
Dim parameters As Object() = {ControlStyles.OptimizedDoubleBuffer Or ControlStyles.AllPaintingInWmPaint, True}
method.Invoke(P_List_LB, parameters)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:12:02