Оновлення:
За словами @donovan, сучасні WPF підтримують це споконвічно, через налаштування
ShowInTaskbar="False"
та Visibility="Hidden"
в XAML. (Я ще не перевіряв цього, але все ж вирішив покращити видимість коментарів)
Оригінальна відповідь:
Існує два способи приховування вікна від перемикача завдань в API Win32:
- додати
WS_EX_TOOLWINDOW
розширений стиль вікна - це правильний підхід.
- щоб зробити його дочірнім вікном іншого вікна.
На жаль, WPF не підтримує такий гнучкий контроль за стилем вікна, як Win32, таким чином, вікно WindowStyle=ToolWindow
закінчується за замовчуванням WS_CAPTION
та WS_SYSMENU
стилями, через що у нього є підпис та кнопка закриття. З іншого боку, ви можете видалити ці два стилі, встановивши WindowStyle=None
, проте це не встановить WS_EX_TOOLWINDOW
розширений стиль і вікно не буде приховано від перемикача завдань.
Щоб вікно WPF, WindowStyle=None
яке також приховане від перемикача завдань, можна одним із двох способів:
- перейдіть із зразком коду вище та зробіть вікно дочірнє вікно невеликого прихованого вікна інструменту
- змінити стиль вікна, щоб він також включав
WS_EX_TOOLWINDOW
розширений стиль.
Я особисто віддаю перевагу другому підходу. Знову ж таки, я займаюся деякими вдосконаленими речами, такими як розширення скла у клієнтській зоні та включення малюнка WPF у підписі, так що трохи інтероп не є великою проблемою.
Ось зразок коду для підходу до рішення Win32 інтероп. По-перше, частина XAML:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300"
ShowInTaskbar="False" WindowStyle="None"
Loaded="Window_Loaded" >
Тут нічого надто фантазійного, ми просто оголошуємо вікно з WindowStyle=None
і ShowInTaskbar=False
. Ми також додаємо обробник до події Loaded, де ми будемо змінювати стиль розширеного вікна. Ми не можемо виконати цю роботу в конструкторі, оскільки в цій точці ще немає віконної ручки. Сам обробник подій дуже простий:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowInteropHelper wndHelper = new WindowInteropHelper(this);
int exStyle = (int)GetWindowLong(wndHelper.Handle, (int)GetWindowLongFields.GWL_EXSTYLE);
exStyle |= (int)ExtendedWindowStyles.WS_EX_TOOLWINDOW;
SetWindowLong(wndHelper.Handle, (int)GetWindowLongFields.GWL_EXSTYLE, (IntPtr)exStyle);
}
І заяви про інтероп Win32. Я видалив усі непотрібні стилі з перерахунків, просто щоб зберегти зразок коду тут малим. Крім того, на жаль, SetWindowLongPtr
точка входу не знайдена в user32.dll в Windows XP, отже, хитрість з маршрутизацією виклику SetWindowLong
натомість.
#region Window styles
[Flags]
public enum ExtendedWindowStyles
{
// ...
WS_EX_TOOLWINDOW = 0x00000080,
// ...
}
public enum GetWindowLongFields
{
// ...
GWL_EXSTYLE = (-20),
// ...
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
{
int error = 0;
IntPtr result = IntPtr.Zero;
// Win32 SetWindowLong doesn't clear error on success
SetLastError(0);
if (IntPtr.Size == 4)
{
// use SetWindowLong
Int32 tempResult = IntSetWindowLong(hWnd, nIndex, IntPtrToInt32(dwNewLong));
error = Marshal.GetLastWin32Error();
result = new IntPtr(tempResult);
}
else
{
// use SetWindowLongPtr
result = IntSetWindowLongPtr(hWnd, nIndex, dwNewLong);
error = Marshal.GetLastWin32Error();
}
if ((result == IntPtr.Zero) && (error != 0))
{
throw new System.ComponentModel.Win32Exception(error);
}
return result;
}
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
private static extern IntPtr IntSetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
private static extern Int32 IntSetWindowLong(IntPtr hWnd, int nIndex, Int32 dwNewLong);
private static int IntPtrToInt32(IntPtr intPtr)
{
return unchecked((int)intPtr.ToInt64());
}
[DllImport("kernel32.dll", EntryPoint = "SetLastError")]
public static extern void SetLastError(int dwErrorCode);
#endregion