2

我正在使用 MSVB2005。我想编写一个用户控件,它是一个自动文本滚动器,以平滑的方式垂直滚动固定文本,例如逐个像素(而不是逐行)。这也称为Marquee(例如,在 HTML 中)。

我已经使用计时器实现了这样的控件,在它的每个滴答声中,文本都被渲染到控件的表面上 1 个像素。它工作得很好,但是消耗了相当多的 CPU 功率,因为​​没有使用图形硬件加速,并且所有渲染计算都“落在”主 CPU 上。

我想通过使用内置于操作系统(即 Windows)中的图形机制来提高控件的性能,例如 Form/Control 垂直滚动条。我很确定操作系统在下面使用硬件加速。

我认为我的用户控件可以继承自ScrollableControl类,也可以继承自另一个继承ScrollableControl的类,例如Panel。我这样做了,并且在上述计时器的每个滴答声中 - 执行以下操作:

Y += 1
Me.AutoScrollPosition = New Point(0, Y)

whereY是一个类成员,因此在每个计时器滴答声中增加一个。这也很好用,但是:

1)仅当每次调用控件的OnPaint事件处理程序时都执行文本呈现。如果是这样... 这种形式的解决方案获得了什么?(文本渲染似乎是消耗大部分 CPU 时间的部分)

有没有办法只将整个文本渲染一次到控件的表面,并让操作系统完全管理滚动,即让操作系统在垂直滚动条的每次移动时自动重绘控件的可见区域(无需自行重绘每次调用OnPaint时文本的相关部分)?

2)垂直滚动条可见。我需要它处于活动状态但可见。

你的帮助将非常有义务。

附言

该控件适用于 Winforms 应用程序,因此我现在无法切换到 WPF。我不熟悉 DirectX 和 OpenGL,而且短期内也没有时间学习这些技术。因此,目前,任何这些方向的解决方案都不被认为是可行的。谢谢。

4

1 回答 1

2

您要求进行非常难以实施的优化。特别是希望硬件加速会有所帮助是不可行的,文本渲染没有加速。

Windows 内置了对优化垂直滚动的支持,它在任何现代 Windows 版本上默认启用。这是一个系统范围的设置,名为“拖动时显示窗口内容”。您的要求击败了该选项,它仅适用于具有滚动条并且您明确不想要滚动条的窗口。在 ScrollableControl 派生类上隐藏滚动条不是一种选择。

然而,实现该功能的低级 winapi 函数是公开的,因此您可以在技术上在您自己的控件上调用它们。更高级别的winapi函数是ScrollWindowEx(),它滚动窗口的整个客户区。此函数还公开了由 SW_SMOOTHSCROLL 选项标志启用的“平滑滚动”功能。但是请注意,您不太可能使用该标志,因为您不能直接影响滚动的速率,您还表示您希望通过一次滚动一个像素来自己控制速率。在您尝试过之后,您可能会考虑淡化该要求。

ScrollWindowEx() 使用的底层winapi 函数也暴露出来了,就是ScrollDC() 函数。它放弃了滚动整个客户区的要求。并且没有做任何事情来实现平滑滚动动画。您不太可能需要它。

值得一提的是这些winapi函数是如何实现它们的优化的。诀窍相当简单,它们直接对窗口的像素进行位blit,将它们移动滚动量。硬件加速基本操作。这避免了必须重新绘制它们的需要。从本质上讲,您将免费获得 99% 的像素,给予或接受。

然而,仍然需要文本渲染,需要渲染滚动显示的窗口区域的像素。快速完成这一过程非常重要的是需要付出多少努力才能确定从哪里开始绘画。例如,当您执行诸如自动换行文本之类的操作时,它会非常昂贵。你不知道从哪里开始绘画,直到你从文本开始测量每一行,计算出换行符出现的位置。当您可以将滚动位置直接映射到行号时,它会很快。或者您跟踪您之前计算的换行位置。

这里只是一些提示,您的问题对实施细节不够具体,无法判断这些考虑是否适用。您可以使用 pinvoke.net 网站获取所需的 pinvoke 声明。

于 2013-06-30T16:26:06.873 回答