Обновить:
Согласно @donovan, в наши дни WPF поддерживает это изначально, через настройки
ShowInTaskbar="False"
и Visibility="Hidden"
в XAML. (Я это еще не тестировал, но все же решил поднять видимость комментария)
Оригинальный ответ:
Есть два способа скрыть окно от переключателя задач в Win32 API:
- добавить
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