Размытие за прозрачным окном WPF
Я пытаюсь создать приложение WPF с полупрозрачным окном без рамки, которое размывает фон за ним.
Вот пример того, что я хочу сделать. Скриншот
Я пытался использовать DwmEnableBlurBehindWindow
который работает только на Windows Vista/7.
Я пытаюсь найти решение, которое будет работать на Windows 7, 8 и 10.
4 ответа
Для тех, кто заинтересован, я нашел решение для Windows 10. Похоже, что это невозможно в Windows 8, как отметил Дэвид Хеффернан, DwmEnableBlurBehindWindow был удален из Windows 8, однако Microsoft повторно представила решение для достижения этого эффекта в Windows 10.
- Windows 10: решение с использованием SetWindowCompositionAttribute
- Windows 8: нет решения
- Windows 7: вы можете продолжать использовать DwmEnableBlurBehindWindow
Надеюсь, я не опоздал на вечеринку. Вы можете использовать SetWindowCompositionAttribute, но затем вы будете вынуждены установить WindowStyle на "None" и реализовать свою собственную функциональность и дескрипторы Window. Также наследование от пользовательского элемента управления довольно сложно. Тем не менее, короче говоря. Есть BlurryControls.
Вы можете найти его через NuGet, выбрав "BlurryControls" или самостоятельно проверить код на GitHub. В любом случае, я надеюсь, что это полезно.
На GitHub вы также найдете пример приложения.
Windows 8
Как бы тупик, который лучше было бы полностью забыть, нам, возможно, потребуется убедиться, что наши программы работают одинаково в разных версиях. Если нет необходимости в динамическом фоне и, особенно, если окно относительно маленькое (основным кандидатом может быть окно сообщения или подобное в нашем собственном окне приложения), решение захвата экрана за окном и размытия его вручную может работать, в Loaded
обработчик события:
var screen = window.Owner.PointToScreen(new System.Windows.Point((window.Owner.ActualWidth - window.ActualWidth) / 2, (window.Owner.ActualHeight - window.ActualHeight) / 2));
var rect = new Rectangle((int)screen.X, (int)screen.Y, (int)window.ActualWidth, (int)window.ActualHeight);
var bitmap = new Bitmap(rect.Width, rect.Height);
using (var graphics = Graphics.FromImage(bitmap))
graphics.CopyFromScreen(rect.Left, rect.Top, 0, 0, rect.Size);
border.Background = new ImageBrush(ApplyGaussianBlur(bitmap.ToBitmapImage())) {
TileMode = TileMode.None,
Stretch = Stretch.None,
AlignmentX = AlignmentX.Center,
AlignmentY = AlignmentY.Center,
};
где border
является самым внешним Border
Обычно остается полностью пустым, используется только в Windows 8.
Вспомогательная функция - это обычное преобразование растрового изображения:
public static BitmapSource ToBitmapImage(this System.Drawing.Bitmap image) {
var hBitmap = image.GetHbitmap();
var bitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
DeleteObject(hBitmap);
return bitmap;
}
ApplyGaussianBlur()
Лучше всего решить с помощью пакета прямых битовых манипуляций, таких как WriteableBitmapEx
, с необходимыми изменениями.
Microsoft удалила эффекты стекла, начиная с Windows 8. Это объясняет, почему ожидаемый эффект размытия не наблюдается в Windows 8 и более поздних версиях. Вам придется научиться жить без него в этих операционных системах.