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

StackOverflow https://stackoverflow.com/questions/357076

  •  21-08-2019
  •  | 
  •  

Вопрос

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

Обновлять: Пожалуйста, смотрите мое опубликованное решение ниже.Мне не разрешено отмечать собственные ответы как решение, но пока это единственное, что работает.

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

Это было полезно?

Решение

Обновлять:

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

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

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

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

К сожалению, WPF не поддерживает такой гибкий контроль над стилем окна, как Win32, поэтому окно с WindowStyle=ToolWindow заканчивается значением по умолчанию WS_CAPTION и WS_SYSMENU Styles, что приводит к появлению заголовка и кнопки закрытия.С другой стороны, вы можете удалить эти два стиля, установив 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

Другие советы

Внутри класса формы добавьте это:

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» и повторно использовать его для всех окон вашего приложения, которые необходимо скрыть от Альтернативный вариант+↹Вкладка.

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

Спасибо Ивану Онучину на форумах MSDN за решение.

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

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

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

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

Вот что помогает, независимо от стиля окна, от которого вы пытаетесь скрыться. Альтернативный вариант+↹Вкладка.

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

// Keep this program out of the Alt-Tab menu

ShowInTaskbar = false;

Form form1 = new Form ( );

form1.FormBorderStyle = FormBorderStyle.FixedToolWindow;
form1.ShowInTaskbar = false;

Owner = form1;

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

Зачем пытаться так много кодов?Просто установите 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":

<Window x:Class="WpfApplication5.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    ShowInTaskbar="False"    
    Title="Window1" Height="300" Width="300">
    <Grid>

    </Grid>
</Window>

Редактировать:Я думаю, это все еще отображается в Alt + Tab, но не на панели задач.

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

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

Это работает отлично :)

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

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

Свойства формы1:
ФормБордерСтиль:Значительный
ОкноСостояние:Минимизированный
Показать панель задач:ЛОЖЬ

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;

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

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

подробнее

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

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

Если хотите, я могу найти в своем блоге статью о создании приложения, которое по умолчанию является ТОЛЬКО NotifyIcon.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top