Опрос
Вы участвуете в программе Windows Insider?
Популярные новости
Обсуждаемые новости

15.06.2006 02:25 | Raiker

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

Источник: http://blogs.msdn.com/adam_nathan/
Перевод: Райкер

Комментарии

Не в сети

Супер!

15.06.06 06:38
0
Не в сети

[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));
}

19.03.08 11:41
0
Для возможности комментировать войдите в 1 клик через

По теме

Акции MSFT
420.55 0.00
Акции торгуются с 17:30 до 00:00 по Москве
Все права принадлежат © ms insider @thevista.ru, 2022
Сайт является источником уникальной информации о семействе операционных систем Windows и других продуктах Microsoft. Перепечатка материалов возможна только с разрешения редакции.
Работает на WMS 2.34 (Страница создана за 0.032 секунд (Общее время SQL: 0.016 секунд - SQL запросов: 57 - Среднее время SQL: 0.00029 секунд))
Top.Mail.Ru