我正在使用MSVB2005。我想编写一个用户控件,它是一个自动文本滚动条,以平滑的方式垂直滚动固定文本,例如逐个像素(和不逐行)。这也称为 Marquee (例如,在HTML中)。
我已经使用计时器实现了这样的控制,在每个计时器上,文本以1像素向上呈现在控件的表面上。它工作得非常好,但由于没有使用图形硬件加速,并且所有渲染计算都“落在”主CPU上,因此消耗了相当多的CPU能力。
我想通过使用内置于操作系统(即Windows)中的图形机制来提高控件的性能,例如Form / Control垂直滚动条。我很确定操作系统会在下面使用硬件加速。
我认为我的用户控件可以继承自 ScrollableControl 类,或者继承自 ScrollableControl 的其他类,例如 Panel 。 我这样做了,在上述计时器的每个滴答声中 - 执行以下操作:
Y += 1
Me.AutoScrollPosition = New Point(0, Y)
其中Y
是一个类成员,因此在每个计时器滴答时增加一个。
这也很有效,但是:
1)只有在每次调用控件的OnPaint
事件处理程序时执行文本呈现。如果那么......这种形式的解决方案获得了什么? (文本呈现似乎是消耗大部分CPU时间的部分)
有没有办法将WHOLE文本只渲染一次来控制表面,并让操作系统完全管理滚动,即让操作系统在每次移动时自动重新绘制控件的可见区域。垂直卷轴(无需在每次调用 OnPaint 时自行重新绘制文本的相关部分)?
2)垂直滚动条可见。我需要它处于活动状态,但不可见。
你的帮助很大。
P.S。
该控件适用于Winforms应用程序,因此我现在无法切换到WPF。 我不熟悉DirectX和OpenGL,并且很快就没有时间学习这些技术。目前,任何这些方向的解决方案都不可行。感谢。
答案 0 :(得分:2)
您要求的优化很难实现。特别希望硬件加速有助于摆脱困境,文本渲染不会加速。
Windows内置支持优化垂直滚动,默认情况下,它在任何现代Windows版本上启用。这是一个名为“拖动时显示窗口内容”的系统范围设置。您的要求会破坏该选项,它仅适用于具有滚动条且您明确不需要滚动条的窗口。隐藏ScrollableControl派生类上的滚动条不是一种选择。
然而,实现该功能的低级别winapi功能已暴露,因此您可以在技术上将它们按照您自己的控制进行设置。更高级别的winapi函数是ScrollWindowEx(),它滚动窗口的整个客户区域。此功能还公开了“平滑滚动”功能,由SW_SMOOTHSCROLL选项标志启用。但要注意,你不太可能使用那个标志,因为你不能直接影响滚动的 rate ,你还表示你想通过滚动一个像素来自己控制速率。一时间在您尝试完这个后,您可能会考虑降低要求。
ScrollWindowEx()使用的低级winapi函数也是公开的,它是ScrollDC()函数。它降低了滚动整个客户区的要求。并没有做任何事来实现平滑滚动动画。你不太可能需要它。
值得一提的是这些winapi功能如何实现优化。诀窍很简单,它们直接咬住窗口的像素,按滚动量移动它们。 硬件加速的基本操作。这避免了必须重新绘制它们的必要性。你实际上可以免费获得99%的像素,给予或接受。
然而,仍然需要文本渲染,以渲染由滚动曝光的窗口区域的像素。 非常对于快速实现这一点很重要的是需要多少努力来确定从哪里开始绘画。例如,当您执行包装文字等文字时,它会非常昂贵。在从文本开头测量每一行,计算换行发生的位置之前,您不知道从哪里开始绘画。当您可以将滚动位置直接映射到行号时,它会很快。或者,您可以跟踪先前计算的换行位置。
这里只是一些提示,你的问题对于判断这些考虑是否适用的实施细节不够具体。您可以使用pinvoke.net网站获取所需的pinvoke声明。