Частичная прозрачность с C # .NET 3.5 WinForms? - PullRequest
2 голосов
/ 17 мая 2009

Я делаю приложение .NET 3.5 с формой, которая рисует частично прозрачный черный фон. Я переопределяю OnPaintBackground, чтобы выполнить это:

protected override void OnPaintBackground( PaintEventArgs e )
{
    using ( Brush brush = new SolidBrush( Color.FromArgb( 155, Color.Black ) ) )
    {
        e.Graphics.FillRectangle( brush, e.ClipRectangle );
    } 
}

Это работает, но иногда форма прорисовывается сама по себе без очистки экрана, делая прозрачность темнее, чем должна быть. Я пытался играть с Graphics.Flush() и Graphics.Clear(), но это либо не помогает, либо полностью удаляет прозрачность. Есть предложения?

Edit: Вот как это выглядит после запуска приложения слева и после того, как форма несколько раз перерисовывается (в ответ на переключение с одного элемента управления на другой) справа:

Проблема прозрачности http://www.quicksnapper.com/files/5085/17725729384A10347269148_m.png

Редактировать 2: Этим утром я попробовал несколько вещей и заметил, что когда рабочий стол за прозрачными частями меняется, он фактически не перерисовывается. Например, если я открою диспетчер задач и поместу его за окном, вы не увидите, что он обновляется сам. Это имеет смысл с тем, что я видел с уровнями прозрачности. Есть ли функция, заставляющая Windows перерисовывать область за окном?

Редактировать 3: Я попытался изменить несколько свойств формы, но все они приводят к тому, что форма отображает непрозрачный черный цвет:

this.AllowTransparency = true;
this.DoubleBuffered = true;
this.Opacity = .99;

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

Ответы [ 2 ]

3 голосов
/ 17 мая 2009

Думаю, я бы назвал это ожидаемым поведением. Что бы я сделал, это отобразил бы свой фон в растровом изображении в памяти и, в случае рисования, скопировал его в форму (базовая двойная буферизация).

Если я далеко от базы, не могли бы вы опубликовать скриншот? Я не знаю, что я представляю, что вы описываете правильно.

EDIT:

Мне интересно, что вы используете OnPaintBackground ... до .NET, если вы выполняете двойную буферизацию, вы ловите и игнорируете сообщение WM_ERASKBKGND (для предотвращения мерцания), визуализируете ваше изображение во внеэкранный буфер, и скопировать из буфера на экран на WM_PAINT. Итак, попробуйте перейти с OnPaintBackground на OnPaint.

Я не делал слишком много подобных вещей в .NET, но раньше у меня была довольно хорошая работа; Я просто не знаю, будет ли это хорошо или нет!

РЕДАКТИРОВАТЬ 2:

Марк, чем больше я думаю о том, что ты пытаешься сделать, тем больше появляется проблем. Я собирался предложить создать фоновый поток, предназначенный для захвата экрана и его затемнения; однако, чтобы удалить собственную форму, вам нужно установить видимость в false, что может создать другие проблемы ...

Если вы не хотите сдаваться, я бы предложил создать два окна и «связать» их вместе. Создайте полупрозрачное окно (путем установки непрозрачности) для фонового окна и создайте второе «нормальное» окно для переднего плана. Используйте SetWindowRgn в окне переднего плана, чтобы вырезать фон и расположить их друг над другом.

Удачи!

1 голос
/ 17 мая 2009

Graphics.CompositingMode установлено на CompositingMode.SourceCopy? Это должно привести к тому, что рисование фона дважды будет эквивалентно рисованию его один раз, так как он заменит существующие данные альфа / цвета вместо наложения на него.

...