Windows 7 & DWN: знаете ли вы, что не все окна должны подчиняться Flip3D и Aero Peek
- modified:
- reading: 3 minutes
Вы, наверняка, знаете, что в Vista и Windows 7 существует функция Flip3D, а в Windows 7 еще и Aero Peek.
Но вы, наверняка, не знаете, что можно заставить ваше окно (приложение) не подчиняться правилам для всех окон в данных возможностях Windows. Для этого следует изучить Desktop Window Manager API.
Итак, с чего начать? Как всегда, если мы пишем приложение на .net (WinForms или WPF), нам нужно проимпортировать необходимые методы. Стоит заметить, что в случае WinForms получить HWND окна очень просто, для этого есть свойство Form::Handle, в случае же WPF можно воспользоваться классом WindowInteropHelper, так чтобы получить HWND главного окна можно написать так:
IntPtr hwnd = new WindowInteropHelper(Application.Current.MainWindow).Handle;
Вернемся теперь к необходимым функциям. Первая функция на которую стоит обратить внимание – это DwmIsCompositionEnabled, она нам позволяет определить включен ли Aero Glass на компьютере:
public partial class FormSample : Form
{
[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern bool DwmIsCompositionEnabled();
public FormSample()
{
InitializeComponent();
if (Environment.OSVersion.Version.Major < 6)
{
// Dwm не работает, старая версия Windows
}
else if (!DwmIsCompositionEnabled())
{
// Aero Glass и Aero 3D отключены (не поддерживаются)
}
else
{
// Aero Glass и Aero 3D работают
}
}
}
Отлично, теперь мы знаем когда можно “играться” с Dwm, следующая функция, которая поможет нам работать с Dwn – это DwmSetWindowAttribute. Это уже основная функция, при помощи которой мы можем управлять нашим окном и говорить системе как его следует отображать.
Например, действие первое. Задача, мы хотим сделать такое приложение, которое отображается даже тогда, когда пользователь включает режим Aero Peek (действие, похожее на гаджет). Представьте на вашем мониторе куча запущенных окон, вам лень искать необходимое окно при помощи WinKey+Tab, а хочется увидеть нужные окна при помощи WinKey+Space – это может быть и обычный мессенджер, и какой-то ваш профайлер, при помощи которого вы следите за работой чего либо, ну и многое другое. Так, например, вот в этой статье “Joel 'Jaykul' Bennett - Fun with PInvoke and Aero Peek“ описывается как можно сделать это с популярным мессенджером Miranda (с этой статьи меня и заинтересовал Dwn и какие возможности он еще предоставляет). Правда в данной статье используются флаги DwmNCRenderingPolicy, которые на самом деле пригодны для установления значений при использовании флага DWMWA_NCRENDERING_POLICY, а не DWMWA_EXCLUDED_FROM_PEEK. Для обычной формы это можно сделать так:
public partial class FormSample : Form
{
[Flags]
public enum DwmWindowAttribute
{
ExcludedFromPeek = 12
}
[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
public static void RemoveFromAeroPeek(IntPtr hwnd)
{
int attrValue = 1; // TRUE
DwmSetWindowAttribute(hwnd, (int)DwmWindowAttribute.ExcludedFromPeek, ref attrValue, sizeof(int));
}
public FormSample()
{
InitializeComponent();
// Делаем видимым при Aero Peek
RemoveFromAeroPeek(Handle);
}
}
Результат будет таким (это чтобы было более понятно о чем я вообще пишу):
Так же можно заставить свое окно не подчиняться правилам Aero 3D (это когда используем WinKey+Tab для переключения между окнами). Для этого нужно рассмотреть атрибут DWMWA_FLIP3D_POLICY, для него можно установить значения “Обычное поведение”, “Показывать поверх 3D”, “Показывать за 3D”, правда у меня работало либо “обычное поведение”, либо “показывать за 3D”, поверх не получилось сделать.
{
[Flags]
public enum DwmWindowAttribute
{
Flip3DPolicy = 8
}
// Flip 3D policies
public enum Flip3DPolicy
{
Default = 0,
ExcludeBelow,
ExcludeAbove
}
[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
public static void SetFlip3DPolicy(IntPtr hwnd)
{
int attrValue = (int)Flip3DPolicy.ExcludeBelow;
DwmSetWindowAttribute(hwnd, (int)DwmWindowAttribute.Flip3DPolicy, ref attrValue, sizeof(int));
}
public FormSample()
{
InitializeComponent();
SetFlip3DPolicy(Handle);
}
}
Результат следующий:
Как это можно использовать – уже сложнее представить. Ну…, мое дело рассказать :) Удачи!
See Also
- WPF: BindingExpression и Nullable<T>
- Работа с окнами как в Windows 7 при помощи hotkeys: Win + [Up|Down|Left|Right]
- История одного Upgrade с Vista x64 на Windows 7 x64, а так же Win7 vs WSUS и WPF vs NVIDIA
- WPF - использование навигации по страницам, добавление контролов в NavigationWindow
- WPF – MenuItem и важное свойство CommandTarget