.net - 使用控制垂直滚动条形成跑马灯

标签 .net user-controls scroll scrollbar

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

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

我想通过使用操作系统(即 Windows)内置的图形机制(例如表单/控件垂直滚动条)来提高控件的性能。我很确定操作系统在底层使用了硬件加速。

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

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

其中 Y 是类成员,因此在每个计时器滴答时加一。 这也很有效,但是:

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

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

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

非常感谢您的帮助。

附注

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

最佳答案

您要求的优化很难实现。特别希望硬件加速能有所帮助是不可能的,文本渲染不会加速。

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

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

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

值得一提的是这些winapi函数是如何实现优化的。技巧相当简单,它们直接对窗口的像素进行位 block 传输,按滚动量移动它们。硬件加速的基本操作。这避免了重新粉刷它们的需要。本质上,您将免费获得 99% 的像素,无论给予还是索取。

但是仍然需要文本渲染,需要渲染滚动暴露的窗口区域的像素。要做到这一点,非常重要的是需要付出多少努力来弄清楚从哪里开始绘画。例如,当您执行诸如自动换行之类的操作时,成本将非常昂贵。在测量了从文本开头开始的每一行并计算出换行符发生的位置之前,您不知道从哪里开始绘制。当您可以直接将滚动位置映射到行号时,速度会很快。或者您可以跟踪之前计算的换行符位置。

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

关于.net - 使用控制垂直滚动条形成跑马灯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17391185/

相关文章:

c# - 调试时变量在当前上下文中不存在

.net - WebRole 和 HttpHandler 中的不同 AppDomain

c# - 在 UserControl 内的 asp.net 标签上使用 AssociatedControlID

.net - 如何从 WinForms 应用程序中用户控件上的子控件中获取事件?

jquery - 滚动时如何使元素淡入/淡出

javascript - 使用 jQuery 平滑跨浏览器对 Angular 线滚动

c# - Stange 删除 observablecollection 上的行为

.net - VB.NET : "Statement lambdas cannot be converted to expression trees" compile time error

javascript - 无法通过外部页面上的 javascript 访问用户控件

Android:在 TextView 中自动滚动文本