Размещение прозрачности Aero Glass внутри окон WPF
Говорит Адам Натан, ведущий блога MSDN: Не так давно Тим опубликовал статью о расширении прозрачности внутри окон Windows Forms. Похоже, что со временем он собирается показать этот пример с использованием WPF. Но я не сдержался поделиться одним экспериментом, проведенным мною с WPF и заготовленным для будущей книги по WPF. Так что, Тим, извини, если я отнял у тебя хлеб!..
Примечание: данный код требует WPF Beta 2 и выше (и Windows Vista). Я выпущу весь проект (включая обновление для Internet Hearts) позже.
Итак, я взял WPF UI, разработанный для Internet Hearts, засунул его в System.Windows.Window и «опрозрачнил». Вот что получилось:
Я ничего не менял здесь по сравнению с Hearts UI, и все работает как и запланировано: 2D и 3D анимация, прозрачные элементы и т.д.
Особенно красиво это смотрится при включении Flip3D (который я нашел намного более практичным, чем привычный ALT+TAB).
Конечно, этим я нарушаю все правила использования стилей, практичности, и быстродействия, чрезмерно используя стекло… но это очень интересное упражнение!
Все что требуется, это функция, расширяющая границы WPF окна:
public class GlassHelper
{
public static bool ExtendGlassFrame(Window window, Thickness margin)
{
if (!DwmIsCompositionEnabled())
return false;
IntPtr hwnd = new WindowInteropHelper(window).Handle;
if (hwnd == IntPtr.Zero)
throw new InvalidOperationException("The Window must be shown before extending glass.");
// Set the background to transparent from both the WPF and Win32 perspectives
window.Background = Brushes.Transparent;
HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = Colors.Transparent;
MARGINS margins = new MARGINS(margin);
DwmExtendFrameIntoClientArea(hwnd, ref margins);
return true;
}
Итак, нам нужен HWND, чтобы пройти к DwmExtendFrameIntoClientArea и WindowInteropHelper. MARGINS контролирует насколько расширить прозрачность каждой из четырех сторон. Чтобы получить эффект стеклянного листа вы можете установить параметр -1 для всех сторон.
Но вся хитрость состоит в том, чтобы не просто установить фон окна на прозрачный, но также BackgroundColor с соответствии с CompositionTarget (по-умолчанию черный).
Структура MARGINS схожа с WPF Thickness, поэтому я решил выставить Thickness через ExtendGlassFrame.
struct MARGINS
{
public MARGINS(Thickness t)
{
Left = (int)t.Left;
Right = (int)t.Right;
Top = (int)t.Top;
Bottom = (int)t.Bottom;
}
public int Left;
public int Right;
public int Top;
public int Bottom;
}
Два API DWM определяются следующим образом.
[DllImport("dwmapi.dll", PreserveSig=false)]
static extern void DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
[DllImport("dwmapi.dll", PreserveSig=false)]
static extern bool DwmIsCompositionEnabled();
Finally, the Window calls ExtendGlassFrame inside OnSourceInitialized:
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// This can't be done any earlier than the SourceInitialized event:
GlassHelper.ExtendGlassFrame(this, new Thickness(-1));
}
Отметьте, что Theckness я выставил единственное значение (-1), которое будет использоваться для всех четырех сторон MARGIN.
В ближайшее время я добавлю dwmapi.dll (и другие Windows Vista DLL) на pinvoke.net, чтобы новички могли приступить к освоению новых API. Наслаждайтесь!
Источник:
Перевод: Райкер
Комментарии
[DllImport("dwmapi.dll", PreserveSig=false)]
static extern void DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
[DllImport("dwmapi.dll", PreserveSig=false)]
static extern bool DwmIsCompositionEnabled();
Finally, the Window calls ExtendGlassFrame inside OnSourceInitialized:
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// This can't be done any earlier than the SourceInitialized event:
GlassHelper.ExtendGlassFrame(this, new Thickness(-1));
}
Редактор, поправьте на следующее:
[DllImport("dwmapi.dll", PreserveSig=false)]
static extern void DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
[DllImport("dwmapi.dll", PreserveSig=false)]
static extern bool DwmIsCompositionEnabled();
Наконец, Window (WPF окно) вызывает ExtendGlassFrame внутри OnSourceInitialized:
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// This can't be done any earlier than the SourceInitialized event:
GlassHelper.ExtendGlassFrame(this, new Thickness(-1));
}
По теме
- Создаем контекстно-зависимое WPF-приложение
- #024 – Знакомство с WPF/E
- #023 – Введение в WPF, reloaded…
- #022 Введение в Microsoft Interactive Designer RC1
- #021 Применение 3D в WPF - Часть 2
- #020 Применение 3D в WPF - Часть 1
- #019 Введение в возможности 3D на WPF
- #018 Размещение контрола NET 2.0 на форме WPF
- #017 Первое Web-приложение / Подробнее о Grid / Элемент Frame
- #016 EXE, XBAP, XAML? - Все равно!