Размещение прозрачности Aero Glass внутри окон WPF

Автор: Topol Воскресенье, Май 6th, 2012 Нет комментариев

Рубрика: Операционные системы

Говорит Адам Натан, ведущий блога 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. Наслаждайтесь!

Источник: thevista.ru

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты