双缓冲列表框
我有一个 CheckedListBox (WinForms) 控件(它继承自 ListBox;谷歌搜索显示问题出在 ListBox),该控件锚定到其窗体的所有四个边。 当调整表单大小时,列表框会出现难看的闪烁。 我尝试继承CheckedListBox并在构造函数中将DoubleBuffered
设置为true
(此技术适用于其他控件,包括ListView和DataGridView),但没有效果。
我尝试将 WS_EX_COMPOSITED
样式添加到 < code>CreateParams,这有帮助,但使表单调整大小变得更慢。
有没有其他方法可以防止这种闪烁?
I have a CheckedListBox (WinForms) control (which inherits from ListBox; googling shows that the problem is with ListBox) that is anchored to all four sides of its form. When the form is resized, the ListBox has an ugly flicker. I tried inheriting CheckedListBox and setting DoubleBuffered
to true
in the ctor (this technique works with other controls, including ListView and DataGridView), but it had no effect.
I tried adding the WS_EX_COMPOSITED
style to CreateParams
, and this helped, but makes the form resize mush more slowly.
Is there any other way to prevent this flickering?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以检查切换到带有复选框的 ListView 控件是否会改善问题。 这并不容易处理(但是,嘿,WinForms ListBox 也不是天才之举),我发现使用
DoubleBuffered=true
调整大小的行为是可以忍受的。或者,您可以尝试通过覆盖父窗体背景绘图来减少闪烁 - 提供空心画笔,或通过不执行任何操作并返回
TRUE
来覆盖WM_ERASEBKND
。 (如果你的控件覆盖了父窗体的整个客户区那就没问题,否则你需要更复杂的背景绘制方法。我已经在Win32应用程序中成功使用了这个方法,但我不知道Forms控件是否添加了一些它自身的魔力使其无法发挥作用。
You could check if switching to a ListView Control with checkboxes improves matters. It's not as easy to deal with (but hey, the WinForms ListBox isn't a stroke of genius either), I found that it's resize behavior with
DoubleBuffered=true
is bearable.Alternatively, you could try to reduce flicker by overriding the parent forms background drawing - either providing a hollow brush, or overriding
WM_ERASEBKND
by doing nothing and returningTRUE
. (that's ok if your control covers the entire client area of the parent form, otherwise you'd need a more complex background drawing method.I've used this successfully in Win32 applications, but I don't know if the Forms control adds some of it's own magic that renders this nonfunctional.
这过去是通过向控件发送 WM_SETREDRAW 消息来处理的。
另请参阅:Microsoft 的 WM_SETREDRAW 参考 < em>固定链接
如果其他人在.NET下使用过Windows消息,请根据需要更新此帖子。
This used to be handled by sending the WM_SETREDRAW message to the control.
See also: WM_SETREDRAW reference at Microsoft Fixed Link
If anyone else has used windows messages under .NET, please update this posting as necessary.
尽管没有解决闪烁的具体问题,但对于此类问题通常有效的方法是缓存 ListBox 项的最小状态。 然后通过对每个项目执行一些计算来确定是否需要重绘 ListBox。 仅当至少有一项需要更新时才更新 ListBox(当然,并将此新状态保存在缓存中以供下一个周期使用)。
Although not addressing the specific issue of flickering, a method that is frequently effective for this type of issue is to cache a minimal state of the ListBox items. Then determine whether you need to redraw the ListBox by performing some calculation on each item. Only update the ListBox if at least one item needs to be updated (and of course save this new state in the cache for the next cycle).
尽管是所有者绘制的列表框,但我也遇到了类似的问题。 我的解决方案是使用 BufferedGraphics 对象。 如果您的清单不是业主绘制的,则此解决方案的效果可能会有所不同,但也许它会给您一些灵感。
我发现 TextRenderer 很难渲染到正确的位置,除非我提供 TextFormatFlags.PreserveGraphicsTranslateTransform。 另一种方法是使用 P/Invoke 调用 BitBlt 在图形上下文之间直接复制像素。 我选择这个是两害相权取其轻。
GDI
类(由 frenchtoast 建议)。I was having similar issues albeit with an owner drawn listbox. My solution was to use BufferedGraphics objects. Your mileage may vary with this solution if your list isn't owner drawn, but maybe it will give you some inspiration.
I found that TextRenderer had difficulties rendering to the correct location unless I suppled TextFormatFlags.PreserveGraphicsTranslateTransform. The alternative to this was to use P/Invoke to call BitBlt to directly copy pixels between the graphics contexts. I chose this as the lesser of two evils.
The
GDI
class (suggested by frenchtoast).