Pull to refresh

Добавление эффекта окна Aero Glass

Reading time2 min
Views1.6K
Наверно все, кто работал с Windows Vista (есть ведь ещё к примеру заядлые XPшники которые и Aero в глаза не видели :)), видели так называемый Aero Glass эффект — один из отличительных эффектов Windows Vista в режиме Aero. По умолчанию этот эффект распространяется на заголовки не развернутых окон и имеет вид размывчатости содержимого других окон находящихся за заголовком активного окна:

image

Данный эффект можно расширить в клиенскую область окна, о чем пойдет речь дальше. Как пример окно проводника Windows Vista, который видно на скриншоте выше. Эффект в проводнике распростроняется на клиенскую область где находятся контролы. Естественно, это будет работать только на Windows Vista. Поэтому перед тем как применить этот эффект, мы должны сделать проверку версии Windows (ниже и далее код с использованием C#):
if (Environment.OSVersion.Version.Major >= 6)
{
// Vista features are supported.
}


Также нужно знать что есть ограничение на использование эффекта: зона эффекта всегда начинается от границ окна, то есть нельзя создать «стеклянный» кусок где-то всередине окна. Это можно обойти с использованием непрозначных контролов если применить эффект на всё окно.

Итак, для эффекта нужно использовать Win API DwmExtendFrameIntoClientArea() расположенную в библиотеке DwmApi.dll:
[DllImport("DwmApi.dll")]
public static extern int DwmExtendFrameIntoClientArea(
IntPtr hwnd,
ref Margins pMarInset);


Структура Margins определяет на сколько пикселей расширить зону эффекта вглубь клиенской области окна
Теперь объявим структуру Margins:
[StructLayout(LayoutKind.Sequential)]
public struct Margins
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}


Теперь можно собственно вызвать метод, в данном случае расширяем зону эффекта в клиенскую область вниз на 50 пикселей:
private void Form1_Load(object sender, EventArgs e)
{
margins = new Margins();
margins.cxLeftWidth = 0;
margins.cxRightWidth = 0;
margins.cyTopHeight = 50;
margins.cyBottomHeight = 0;

int retValue = DwmExtendFrameIntoClientArea(this.Handle, ref margins);

if (retValue < 0)
throw new NotSupportedException();
}


Эффект должен применяться перед появлением окна, или же надо будет пересоздать окно:
this.RecreateHandle();


Но это не всё. Если мы сейчас выполним код, то вместо «стекла» увидим черную полосу. Это происходит потому, что GDI не имеет понятия о альфа канале, использование черной кисти в зоне эффекта решает проблему:
protected override void OnPaintBackground(PaintEventArgs e)
{
e.Graphics.FillRectangle(Brushes.Black, 0, 0, this.ClientSize.Width, margins.cyTopHeight);
}


Теперь запускаем и видим заветное окно:
image

Принцип понятен. Остальное, как например распространение эффекта на всю область окна или добавление возможности перетаскивания мышью на зону эффекта, дело техники.
Tags:
Hubs:
Total votes 20: ↑13 and ↓7+6
Comments14

Articles