gpt4 book ai didi

c# - 为什么 ListView 对某些字符的渲染速度如此之慢?

转载 作者:太空狗 更新时间:2023-10-29 23:38:09 24 4
gpt4 key购买 nike

更新 1:我已经编写了一个 MFC-C++ 实现和一个老式的 Win32 应用程序,并录制了一段视频来展示这个问题到底有多严重:

https://www.youtube.com/watch?v=f0CQhQ3GgAM

由于老式的 Win32 应用程序没有出现这个问题,这让我相信 C# 和 MFC 都使用相同的渲染 API,这一定会导致这个问题(基本上消除了我对问题可能出在操作系统/图形驱动程序级别)。


原帖:

当必须在 ListView 中显示一些 REST 数据时,我遇到了一个非常特殊的问题:

对于某些输入,ListView 呈现在水平滚动时会慢得像爬行一样。

在我的系统和带有“OptimizedDoubleBuffer”的典型子类 ListView 中,ListView 中只有 6 个项目会在滚动到我可以看到标题“游动”的点时减慢渲染速度,即项目的渲染和滚动不匹配期间的标题。

对于具有 10 个项目的常规非子类 ListView,我可以在滚动时真正看到每个项目被单独绘制(重新绘制大约需要 1-2 秒)。

这是示例代码(是的,我知道这些看起来像熊和蝴蝶表情;毕竟这个问题是从用户提供的数据中发现的):

using System;
using System.Windows.Forms;

namespace SlowLVRendering
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
}

private void Form1_Load(object sender, EventArgs e)
{
const string slow = "ヽ( ´。㉨°)ノ Ƹ̴Ӂ̴Ʒ~ ღ ( ヽ( ´。㉨°)ノ ༼ つ´º㉨º ༽つ ) (」゚ペ)」ヽ( ´。㉨°)ノ Ƹ̴Ӂ̴Ʒ~ ღ ( ヽ( ´。㉨°)ノ ༼ つ´º㉨º ༽つ ) (」゚ペ)」";
ListView lv = new ListView();
lv.Dock = DockStyle.Fill;
lv.View= View.Details;
for (int i = 0; i < 2; i++) lv.Columns.Add("Title "+i, 500);
for (int i = 0; i < 10; i++)
{
var lvi = lv.Items.Add(slow);
lvi.SubItems.Add(slow);
}
Controls.Add(lv);
}
}
}

谁能解释一下问题是什么,以及如何解决?

最佳答案

在尝试了几种不同的方法后,这是我找到的最快的解决方案。仍然有一点犹豫,但与您的原始解决方案相去甚远。在 Microsoft 决定使用比 GDI+ 更好的东西之前,它不会变得更好,除非你使用 .NET 4 及更高版本的 WPF。好吧。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SlowLVRendering
{
[System.Runtime.InteropServices.DllImport("user32")]
private static extern bool SendMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);

private uint LVM_SETTEXTBKCOLOR = 0x1026;

public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);

}
private void Form1_Load(object sender, EventArgs e)
{
const string slow = "ヽ( ´。㉨°)ノ Ƹ̴Ӂ̴Ʒ~ ღ ( ヽ( ´。㉨°)ノ ༼ つ´º㉨º ༽つ ) (」゚ペ)」ヽ( ´。㉨°)ノ Ƹ̴Ӂ̴Ʒ~ ღ ( ヽ( ´。㉨°)ノ ༼ つ´º㉨º ༽つ ) (」゚ペ)」";
ListView lv = new BufferedListView();
// new ListView();
//new ListViewWithLessSuck();

lv.Dock = DockStyle.Fill;
lv.View = View.Details;
for (int i = 0; i < 2; i++) lv.Columns.Add("Title " + i, 500);
for (int i = 0; i < 10; i++)
{
var lvi = lv.Items.Add(slow);
lvi.SubItems.Add(slow);
}
Controls.Add(lv);
//SendMessage(lv.Handle, LVM_SETTEXTBKCOLOR, IntPtr.Zero, unchecked((IntPtr)(int)0xFFFFFF));

}

}
public class BufferedListView : ListView
{
public BufferedListView()
: base()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
}
}
class ListViewWithLessSuck : ListView
{
[StructLayout(LayoutKind.Sequential)]
private struct NMHDR
{
public IntPtr hwndFrom;
public uint idFrom;
public uint code;
}

private const uint NM_CUSTOMDRAW = unchecked((uint)-12);

protected override void WndProc(ref Message m)
{
if (m.Msg == 0x204E)
{
NMHDR hdr = (NMHDR)m.GetLParam(typeof(NMHDR));
if (hdr.code == NM_CUSTOMDRAW)
{
m.Result = (IntPtr)0;
return;
}
}

base.WndProc(ref m);
}

}

您可以亲眼看到其中的区别。如果您取消注释 SendMessage 并将 new BufferedListView(); 更改为 new ListViewWithLessSuck(); 您可以看到更改。

关于c# - 为什么 ListView 对某些字符的渲染速度如此之慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30956440/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com