C# 使用大量控件填充FlowLayoutPanel并根据需要绘制缩略图

C# 使用大量控件填充FlowLayoutPanel并根据需要绘制缩略图,c#,.net,winforms,onpaint,flowlayoutpanel,C#,.net,Winforms,Onpaint,Flowlayoutpanel,我正在尝试制作一个ImageListBox控件,它将显示大量的缩略图,就像Picasa使用的那样 这是我的设计: 我有一个FlowLayoutPanel,其中填充了许多UserControl对象,例如4000。 每个UserControl都为Paint事件分配了一个委托。 调用Paint事件时,它会检查内存缓存中的缩略图,如果图像不在缓存中,则会从磁盘中检索图像 我有两个问题要解决: 即使UserControl不在视图中,WinForms似乎也会触发Paint事件。实际上只有10个左右的控件在视

我正在尝试制作一个
ImageListBox
控件,它将显示大量的缩略图,就像Picasa使用的那样

这是我的设计:

我有一个
FlowLayoutPanel
,其中填充了许多
UserControl
对象,例如4000。 每个
UserControl
都为
Paint
事件分配了一个委托。 调用
Paint
事件时,它会检查内存缓存中的缩略图,如果图像不在缓存中,则会从磁盘中检索图像

我有两个问题要解决:

  • 即使
    UserControl
    不在视图中,WinForms似乎也会触发
    Paint
    事件。实际上只有10个左右的控件在视图中,其余的没有(FlowLayoutPanel.AutoScroll设置为
    true
    )。因此,它尝试检索所有图像的缩略图,这需要很长时间

  • UserControl
    对象添加到
    FlowLayoutPanel
    需要一些时间,大约2-3秒。我可以接受,但我想知道是否有比以下更好的方法:

    UserControl[] boxes = new UserControl[N];
    // populate array
    panel.SuspendLayout();
    panel.Controls.AddRange(boxes);
    panel.ResumeLayout();
    

  • 我不会添加那么多用户控件。相反,我需要一系列的数据结构来存储关于使用哪个缩略图、定位等的信息,然后处理所需的每个缩略图的渲染


    当然,您只需要通过检查控件中的paint event args并渲染视图中需要渲染的缩略图来渲染所需的内容。

    Aha!我发现了一些东西


    当UserControl不在视图中并且接收到绘制事件时,e.ClipRectangle.IsEmpty为true

    要提高使用用户控件填充FlowLayoutPanel的速度,请在添加控件时禁用布局更新


    在循环之前,先调用,然后在结束调用时调用。确保使用try finally确保即使出现异常,也能运行
    ResumeAlayout()。我正在使用“合同”,它可以有x行(fl面板中的x个控件),我也看到了用所有控件填充面板的时间很长。200件物品需要2-3秒(与您的情况相比,甚至不是4000件)。我肯定会“喜欢”这个问题我在填充对象时使用suspendlayout/resumelayout和visible true/false,这对于我所需要的东西来说太复杂了。添加控件并不是什么大问题。如何解决问题(1)?应用程序可以拥有的窗口句柄数量有一个全局上限。每个用户控件都会生成至少一个句柄(如果内部有其他控件,则会生成更多句柄),如果超过允许的句柄数,则应用程序将崩溃。操作系统将允许大约10K个句柄,就像在我的情况下,浏览器应用程序中可能有200K-300K图标,分页是唯一的选项。