WPF пользовательский рисунок и прозрачность - как оптимизировать? - PullRequest
2 голосов
/ 04 марта 2011

У меня есть приложение WPF с пользовательским стилем окон (AllowsTransparency = "True" WindowStyle = "None"). В этом окне есть пользовательский элемент управления Peak Meter, который использует WriteableBitmap для извлечения данных из аудиовхода DirectSound.

Я использую растровое изображение со всеми уровнями, нарисованными в виде цветных прямоугольников (красный / желтый / зеленый / красный), и когда звук поступает, я просто рисую черный прямоугольник над уровнемером сверху. Он отлично работает на моей машине (Windows 7, Pentium 4 одноядерный). Но он плохо работает на ноутбуке с Windows XP SP3 и встроенным видео.

Я знаю, что у эффектов прозрачности есть некоторые проблемы в DirectX 9, но я прочитал, что проблема должна быть исправлена ​​в SP3. Тем не менее, вызов _writeableBitmap.AddDirtyRect занимает 30-40% ЦП в XP и иногда вызывает пропадание звука (если используется звук USB, и эти пропадания происходят не в моем приложении, а где-то в подсистеме драйверов DirectSound <->).

В Windows 7 одно и то же приложение занимает не более 3% ЦП, при этом пропадание звука не замечено (но ЦП фактически слабее на ПК с Win7, чем на ноутбуке с XP).

Я пытался не использовать AddDirtyRect, а просто нарисовать элемент WPF Rectangle поверх изображения с помощью светодиодов и установить высоту прямоугольника при появлении нового уровня звука. Какой сюрприз! Каким-то образом изменение высоты элемента Rectangle требует заметно меньше ресурсов, чем вызов _writeableBitmap.AddDirtyRect для прямоугольника размером 100x20 пикселей! Теперь на XP это заняло всего 10-20% вместо 30-40% с AddDirtyRect.

Но когда я удалил эффект прозрачности из окна, наконец, XP (и даже на VirtualBox) снизился до 2-6% CPU. Очевидно, что из-за прозрачности очень трудно перерисовывать прямоугольник 20x100 10 раз в секунду.

Я мог бы жить без прозрачности в моем приложении, но проблема в том, что в дизайне используются окна с закругленными углами, и мне нужно обрезать область вокруг них. Но как только я установлю AllowsTransparency = "False", в окне появится цвет фона позади.

Итак, главный вопрос - как сделать так, чтобы содержимое окна отсекало фон окна, чтобы углы оставались круглыми, не используя прозрачность с высоким уровнем XP?

Я помню, что я мог сделать больше, чем даже в приложении C ++ для Windows, просто установив пользовательскую область окна и не используя никакой прозрачности (которая была на компьютере с Windows 98). Можно ли сделать то же самое в WPF?

Или, может быть, есть какой-то трюк, как заставить WriteableBitmap использовать меньше ресурсов в XP?

1 Ответ

1 голос
/ 06 марта 2011

Поскольку я не нашел ничего лучшего, я использовал старый способ: SetWindowRgn API.

Это было немного сложно, потому что мое приложение использует некоторые анимированные выдвижные части, которые выступают из главного окна, поэтому япришлось синхронизировать анимацию WPF с вызовами SetWindowRgn, чтобы эффект скольжения выглядел максимально чистым.Результат не идеален, но приемлем.И главное - больше нет высоких процессоров и нет пропаданий звука.

...