2013-06-30 6 views
1

Я использую MSVB2005. Я бы хотел написать пользовательский элемент управления, который является автоматическим скроллером, прокручивая фиксированный текст по вертикали, плавно, например. пиксель на пиксель (и нет line-by-line). Это также известно как Marquee (в HTML, например).Использование контрольного вертикального скроллера для формирования выделения

Я уже реализовал такой элемент управления, используя таймер, который на каждом из его тиков выводит текст на поверхность элемента управления 1 пиксель вверх. Он работает очень хорошо, НО потребляет довольно большую мощность процессора, так как графическое аппаратное ускорение не используется, и все вычисления вычислений «падают» на основной процессор.

Я хотел бы улучшить производительность управления с помощью графических механизмов, встроенных в ОС (например, Windows), таких как вертикальный скроллер формы/управления. Я уверен, что ОС использует аппаратное ускорение снизу.

Я думал, что мой пользователь-контроль может наследовать от классаScrollableControl, или из другого класса, который наследует ScrollableControl, такие как панель. я сделал это, и после каждого тика вышеупомянутого таймера - выполняется следующее:

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

, где Y является классом-членом, и, следовательно, увеличивается на единицу после каждого тика таймера. Это тоже хорошо работает, НО:

1) только если текст-рендеринг выполняется при каждом вызове OnPaint обработки события элемента управления. Если бы так ... Что было получено этой формой решения? (Текст-рендеринг, кажется, та часть, которая потребляет большую часть процессорного времени)

Есть ли способ, чтобы сделать весь текст только один раз для управления поверхностью, и имеют ОСА полностью управлять прокруткой, то есть пусть OS автоматически перерисовывает видимую область элемента управления при каждом перемещении вертикального скроллера (без необходимости перекрашивать соответствующую часть текста при каждом вызове OnPaint)?

2) Видимая вертикальная полоса прокрутки. Мне нужно, чтобы оно было активным, но не видно.

Ваша помощь будет очень обязательна.

P.S.

Элемент управления предназначен для приложения Winforms, поэтому я не могу переключиться на WPF прямо сейчас. Я не знаком с DirectX и OpenGL, и у меня не было времени узнать какие-либо из этих технологий в ближайшее время. так что в настоящее время решение в любом из этих направлений не будет считаться выполнимым. Благодарю.

ответ

2

Вы запрашиваете оптимизацию, которую довольно сложно реализовать. В частности, в надежде, что аппаратное ускорение поможет не за столом, текстовый рендеринг не ускоряется.

У Windows есть встроенная поддержка оптимизации вертикальной прокрутки, она включена по умолчанию в любой современной версии Windows. Это общесистемный параметр с именем «Показывать содержимое окна при перетаскивании».Ваши требования отменяют этот параметр, он доступен только в окнах с полосой прокрутки, и вы явно не хотите этого. Скрытие полосы прокрутки на производном классе ScrollableControl не является вариантом.

Низкоуровневые функции winapi, которые реализуют эту функцию, однако подвергаются воздействию, поэтому вы можете технически вывести их из-под своего собственного контроля. Функция winapi более высокого уровня - ScrollWindowEx(), она прокручивает всю клиентскую область окна. Эта функция также предоставляет функцию «плавной прокрутки», включенную флажком опций SW_SMOOTHSCROLL. Помните, однако, что вы вряд ли сможете использовать этот флаг, так как вы не можете напрямую влиять на скорость , на которой вы прокручиваете, вы также указали, что хотите сами контролировать скорость, прокручивая по одному пикселю за раз. Вы можете подумать о том, чтобы отказаться от этого требования после того, как вы экспериментировали с этим.

Функция нижнего уровня winapi, которая используется ScrollWindowEx(), также является функцией ScrollDC(). Он отменяет требование прокрутки всей клиентской области. И не делает ничего для реализации анимации с плавной прокруткой. Вряд ли вам это понадобится.

Следует упомянуть, как эти функции winapi достигают своей оптимизации. Трюк довольно прост, они прямо битуют пиксели окна, перемещая их по количеству прокрутки. Основная операция, которую - аппаратное ускорение. Это позволяет избежать необходимости перекрашивать их. Вы, по сути, получите 99% пикселей бесплатно, дайте или возьмите.

Однако требуется рендеринг текста, необходимый для визуализации пикселей области окна, которая была открыта свитком. Что такое very Важно сделать так быстро, сколько усилий требуется, чтобы выяснить, с чего начать рисовать. Это будет, к примеру, очень дорого, когда вы делаете что-то вроде текстового текста. Вы не знаете, где начать рисовать, пока вы не измерили каждую строку с начала текста, вычисляя, где происходит разрыв строки. Это будет быстро, когда вы можете напрямую сопоставить позицию прокрутки с номером строки. Или вы отслеживаете позиции разрыва строки, которые вы рассчитали ранее.

Просто некоторые подсказки здесь, ваш вопрос не был достаточно конкретным относительно деталей реализации, чтобы судить, применяются ли эти соображения. Вы можете использовать веб-сайт pinvoke.net, чтобы получить требуемые объявления pinvoke.

+0

Спасибо за подробный ответ. Я пытаюсь Бит-Blitting. Я прочитал об этом и успешно написал приложение-бит-blitting между полями изображений, но не мог бить blit, чтобы сформировать поверхность-клиент-прямоугольник/управление. Я передаю текст только один раз в Picture-box, а затем при каждом тике вышеупомянутого таймера вызывается 'OnPaint', пытаясь разбить бит из Picture-Box (с вертикальным смещением) на' e. Graphics.GetHdc() '. Это не работает (исключение вызывается), вероятно, потому, что я не должен использовать 'GetHdc()'. Что мне делать? Если возможно, фрагмент будет отличным. – Bliss

+0

Нигде в моем посте я не рекомендовал вам делать блинтинг самостоятельно. Я рекомендовал использовать ScrollWindowEx. –

+0

OK ... Итак, я тестирую 'ScrollWindowEx' сейчас. какую структуру я должен использовать для аргументов 'prcScroll' и' prcClip' (которые, согласно MSDN, должны иметь тип «RECT», который недоступен на моем VB.Net)? Как эта структура должна быть использована для фактического типа этих аргументов - 'IntPtr'? Большое спасибо. – Bliss

Смежные вопросы