Лучший способ скрыть окно от переключателя программ Alt-Tab?

Я уже несколько лет являюсь разработчиком .NET, и это все еще одна из тех вещей, которые я не знаю, как правильно поступать. Легко скрыть окно из панели задач с помощью свойства как в Windows Forms, так и в WPF, но, насколько я могу судить, это не гарантирует (или обязательно влияет на) его скрытие от диалога Alt + ↹Tab . Я видел невидимые windows в Alt + ↹Tab , и мне просто интересно, что лучший способ гарантировать, что окно никогда не появится (видимо или нет) в диалоговом окне Alt + ↹Tab .

Обновление: см. Ниже мое решение. Я не могу пометить свои ответы как решение, но пока это единственное, что работает.

Обновление 2: теперь есть подходящее решение от Франси Пенова, которое выглядит неплохо, но не пробовал самостоятельно. Вовлекает некоторые Win32, но избегает хромого создания внеэкранных окон.

Обновить:

Согласно @donovan, современные WPF поддерживают это изначально, устанавливая ShowInTaskbar="False" и Visibility="Hidden" в XAML. (Я еще не тестировал это, но тем не менее решил повысить видимость комментария)

Оригинальный ответ:

Существует два способа скрытия windows из переключателя задач в Win32 API:

  1. для добавления расширенного стиля windows WS_EX_TOOLWINDOW – это правильный подход.
  2. чтобы сделать его дочерним окном другого windows.

К сожалению, WPF не поддерживает гибкий контроль над стилем windows как Win32, поэтому окно с WindowStyle=ToolWindow заканчивается WindowStyle=ToolWindow по умолчанию и WS_SYSMENU , что приводит к тому, что у него есть подпись и кнопка закрытия. С другой стороны, вы можете удалить эти два стиля, установив WindowStyle=None , однако это не установит расширенный стиль WS_EX_TOOLWINDOW и окно не будет скрыто от переключателя задач.

Чтобы иметь окно WPF с WindowStyle=None , которое также скрыто от переключателя задач, можно использовать один из двух способов:

  • перейдите с примером кода выше и сделайте окно дочерним окном небольшого скрытого windows инструмента
  • измените стиль windows, чтобы также включить расширенный стиль WS_EX_TOOLWINDOW .

Я лично предпочитаю второй подход. Опять же, я делаю некоторые продвинутые вещи, такие как расширение стекла в клиентской области и включение рисунка WPF в подпись в любом случае, поэтому немного взаимодействия не является большой проблемой.

Вот пример кода для решения решения Win32 interop. Во-первых, часть XAML:

  

Здесь нет ничего необычного, мы просто объявляем окно с WindowStyle=None и ShowInTaskbar=False . Мы также добавляем обработчик события Loaded, где мы будем изменять расширенный стиль windows. Мы не можем делать эту работу в конструкторе, поскольку в этот момент нет дескриптора windows. Сам обработчик событий очень прост:

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

И объявления Interop Win32. Я удалил все ненужные стили из перечислений, чтобы сохранить здесь пример кода. К сожалению, SetWindowLongPtr входа 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 

Внутри classа формы добавьте следующее:

 protected override CreateParams CreateParams { get { var Params = base.CreateParams; Params.ExStyle |= 0x80; return Params; } } 

Это так просто; работает прелесть!

Я нашел решение, но это некрасиво. Пока это единственное, что я пробовал, что на самом деле работает:

 Window w = new Window(); // Create helper window w.Top = -100; // Location of new window is outside of visible part of screen w.Left = -100; w.Width = 1; // size of window is enough small to avoid its appearance at the beginning w.Height = 1; w.WindowStyle = WindowStyle.ToolWindow; // Set window style as ToolWindow to avoid its icon in AltTab w.Show(); // We need to show window before set is as owner to our main window this.Owner = w; // Okey, this will result to disappear icon for main window. w.Hide(); // Hide helper window just in case 

Найди его здесь .

Было бы лучше использовать общее, многоразовое решение. Я полагаю, вы могли бы создать одно окно «w» и повторно использовать его для всех окон вашего приложения, которые должны быть скрыты от Alt + ↹Tab .

Обновление: Хорошо, так что я сделал, это переместить вышеуказанный код, минус this.Owner = w бит (и перемещение w.Hide() сразу после w.Show() , который отлично работает) в конструкторе моего приложения, создавая публичную статическую Window именем OwnerWindow . Всякий раз, когда я хочу, чтобы окно this.Owner = App.OwnerWindow это поведение, я просто устанавливаю this.Owner = App.OwnerWindow . Отлично работает и только включает создание одного дополнительного (и невидимого) windows. Вы даже можете установить this.Owner = null если вы хотите, чтобы окно появлялось в диалоговом окне Alt + ↹Tab .

Благодаря Ивану Онучину на форумах MSDN для решения.

Обновление 2: вы должны также установить ShowInTaskBar=false на w чтобы предотвратить кратковременное кратковременное отображение на панели задач, когда показано.

Почему так сложно? Попробуй это:

 me.FormBorderStyle = FormBorderStyle.SizableToolWindow me.ShowInTaskbar = false 

Идея взята отсюда: http://www.csharp411.com/hide-form-from-alttab/

Вот что делает трюк, независимо от стиля windows, которое вы пытаетесь скрыть от Alt + ↹Tab .

Поместите в конструктор своей формы следующее:

 // Keep this program out of the Alt-Tab menu ShowInTaskbar = false; Form form1 = new Form ( ); form1.FormBorderStyle = FormBorderStyle.FixedToolWindow; form1.ShowInTaskbar = false; Owner = form1; 

По существу, вы делаете свою форму дочерним элементом невидимого windows, которое имеет правильный стиль и параметр ShowInTaskbar, чтобы не попадать в список Alt-Tab. Вы также должны установить для свойства ShowInTaskbar вашей собственной формы значение false. Лучше всего, это просто не имеет значения, какой стиль имеет ваша основная форма, и всякая настройка для выполнения скрытия – это всего лишь несколько строк в коде конструктора.

Зачем пробовать столько кодов? Просто установите FormBorderStyle FormBorderStyle в FixedToolWindow . Надеюсь, поможет.

см. его: (с http://bytes.com/topic/c-sharp/answers/442047-hide-alt-tab-list#post1683880 )

 [DllImport("user32.dll")] public static extern int SetWindowLong( IntPtr window, int index, int value); [DllImport("user32.dll")] public static extern int GetWindowLong( IntPtr window, int index); const int GWL_EXSTYLE = -20; const int WS_EX_TOOLWINDOW = 0x00000080; const int WS_EX_APPWINDOW = 0x00040000; private System.Windows.Forms.NotifyIcon notifyIcon1; // I use two icons depending of the status of the app normalIcon = new Icon(this.GetType(),"Normal.ico"); alertIcon = new Icon(this.GetType(),"Alert.ico"); notifyIcon1.Icon = normalIcon; this.WindowState = System.Windows.Forms.FormWindowState.Minimized; this.Visible = false; this.ShowInTaskbar = false; iconTimer.Start(); //Make it gone frmo the ALT+TAB int windowStyle = GetWindowLong(Handle, GWL_EXSTYLE); SetWindowLong(Handle, GWL_EXSTYLE, windowStyle | WS_EX_TOOLWINDOW); 

В XAML установите ShowInTaskbar = “False”:

     

Edit: Это все еще показывает это в Alt + Tab, я думаю, просто не на панели задач.

Я попытался установить видимость основной формы на false, когда она автоматически изменится на true:

 private void Form1_VisibleChanged(object sender, EventArgs e) { if (this.Visible) { this.Visible = false; } } 

Он отлично работает 🙂

Не показывать форму. Используйте невидимость.

Подробнее здесь: http://code.msdn.microsoft.com/TheNotifyIconExample

Свойства Form1:
FormBorderStyle: значимый
WindowState: сведено к минимуму
ShowInTaskbar: False

 private void Form1_Load(object sender, EventArgs e) { // Making the window invisible forces it to not show up in the ALT+TAB this.Visible = false; }> 

если вы хотите, чтобы форма была без полей, вам нужно добавить следующие инструкции в конструктор формы:

 this.FormBorderStyle = FormBorderStyle.None; this.ShowInTaskbar = false; 

И вы должны добавить следующий метод в свой производный class Form:

 protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; // turn on WS_EX_TOOLWINDOW style bit cp.ExStyle |= 0x80; return cp; } } 

подробнее

Лично, насколько я знаю, это невозможно без привязки к windowsм каким-то образом, я даже не знаю, как это будет сделано или если это возможно.

В зависимости от ваших потребностей разработка вашего контекста приложения как приложения NotifyIcon (системного трея) позволит ему работать без отображения в ALT + TAB. ОДНАКО, если вы откроете форму, эта форма по-прежнему будет соответствовать стандартной функциональности.

Я могу выкопать статью в блоге о создании приложения, которое по умолчанию является NotifyIcon, если хотите.

  • Как включить ошибки привязки в исключения во время выполнения?
  • Как отображать элементы в Canvas через Binding
  • INotifyPropertyChanged WPF
  • Как определить ограничения ввода TextBox?
  • Ужасная работа пользовательского контроля
  • Является ли реализация Джошем Смитом RelayCommand ошибочной?
  • C # / WPF: отключить Text-Wrap из RichTextBox
  • Есть ли способ определить, где объявляется / создается привязка WPF?
  • Как создать пользовательский элемент управления WPF с содержимым NAMED
  • Для чего нужен DataContext?
  • ElementName привязка из MenuItem в ContextMenu
  • Давайте будем гением компьютера.