Pergunta

Eu fui um desenvolvedor .NET há vários anos e isso ainda é uma daquelas coisas que eu não sei como fazer corretamente. É fácil esconder uma janela na barra de tarefas através de uma propriedade em ambos os Windows Forms e WPF, mas tanto quanto eu posso dizer, isso não garante (ou necessariamente afetar até mesmo) que está sendo escondido do Alt + ?Tab diálogo. Eu vi invisível janelas aparecem em Alt + ?Tab , e eu estou apenas querendo saber qual é a melhor maneira de garantir uma janela irá não aparecer (visível ou não) no Alt + ?Tab diálogo.

Update: Por favor, veja a minha solução postada abaixo. Eu não estou autorizado a marcar minhas próprias respostas como a solução, mas até agora ele é o único que funciona.

Update 2: Há agora uma solução adequada por Franci Penov que parece muito bom, mas não tentei-lo eu mesmo. Envolve algum Win32, mas evita a criação coxo de janelas fora da tela.

Foi útil?

Solução

Update:

De acordo com @donovan, modernos dias WPF suporta isso nativamente, através de ajuste ShowInTaskbar="False" e Visibility="Hidden" no XAML. (Eu não testei isso ainda, mas mesmo assim decidiu bater o comentário visibilidade)

resposta Original:

Existem duas maneiras de esconder uma janela do switcher tarefa em Win32 API:

  1. para adicionar o WS_EX_TOOLWINDOW estendido estilo da janela -. Essa é a abordagem correta
  2. para torná-lo uma janela filho de outra janela.

Infelizmente, WPF não suporta como controle flexível sobre o estilo de janela como Win32, assim, uma janela com extremidades WindowStyle=ToolWindow-se com o WS_CAPTION padrão e estilos WS_SYSMENU, o que faz com que ele tenha uma legenda e um botão fechar. Por outro lado, você pode remover esses dois estilos, definindo WindowStyle=None, no entanto, que não irá definir o estilo estendido WS_EX_TOOLWINDOW ea janela não será escondido do alternador de tarefas.

Para ter uma janela WPF com WindowStyle=None que também é escondido do alternador de tarefas, pode-se de duas maneiras:

  • ir com o código de exemplo acima e fazer a janela uma janela filho de uma janela pequena ferramenta oculta
  • modificar o estilo de janela para incluir também o estilo estendido WS_EX_TOOLWINDOW.

Eu pessoalmente prefiro a segunda abordagem. Então, novamente, eu faço algumas coisas avançadas como estendendo o vidro na área de cliente e permitindo WPF desenho na rubrica de qualquer maneira, então um pouco de interoperabilidade não é um grande problema.

Aqui está o código de exemplo para o Win32 interoperabilidade abordagem solução. Primeiro, a parte 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" >

Nada muito extravagante aqui, nós simplesmente declarar uma janela com WindowStyle=None e ShowInTaskbar=False. Nós também adicionar um manipulador para o evento Loaded onde iremos modificar a janela estilo estendido. Nós não podemos fazer esse trabalho no construtor, como não há nenhum identificador de janela naquele ponto ainda. O manipulador de eventos em si é muito simples:

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

E o Win32 interoperabilidade declarações. Eu removi todos os estilos desnecessários do enums, apenas para manter o código de exemplo aqui pequena. Além disso, infelizmente, o ponto de entrada SetWindowLongPtr não é encontrado em user32.dll no Windows XP, daí o truque com encaminhamento da chamada através do SetWindowLong vez.

    #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

Outras dicas

Dentro de sua classe de formulário, adicione o seguinte:

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

É tão fácil como isso; trabalha um encanto!

Eu encontrei uma solução, mas não é bonito. Até agora, este é o única coisa que eu tentei que realmente funciona:

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

aqui .

A solução mais geral, reutilizáveis ??seria bom. Eu suponho que você poderia criar uma única janela 'w' e reutilizá-lo para todas as janelas em seu aplicativo que precisam ser escondidos do Alt + ?Tab .

Update: Ok, então o que eu fiz foi mover o código acima, menos o bit this.Owner = w (e w.Hide() imediatamente após w.Show(), que funciona bem em movimento) para o construtor do meu aplicativo, criando um Window public static chamado OwnerWindow. Sempre que eu quero uma janela para apresentar esse comportamento, eu simplesmente definir this.Owner = App.OwnerWindow. Funciona muito bem, e só envolve a criação de um adicional (e invisível) janela. Você pode até mesmo definir this.Owner = null se quiser que a janela para reaparecer no Alt + ?Tab diálogo.

Graças ao Ivan Onuchin Mais em fóruns do MSDN para a solução.

Update 2:. Você deve também definir ShowInTaskBar=false em w para evitar que ele breve piscar na barra de tarefas quando mostrado

Por que tão complexa? Tente isto:

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

Ideia tomada de aqui: http://www.csharp411.com/hide -forma-de-AltTab /

Aqui está o que faz o truque, independentemente do estilo da janela você está tentando esconder de Alt + ?Tab .

Coloque o seguinte para o construtor do seu formulário:

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

ShowInTaskbar = false;

Form form1 = new Form ( );

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

Owner = form1;

Essencialmente, você faz o seu formulário de uma criança de uma janela invisível que tem o estilo correto e configuração ShowInTaskbar para impedir a entrada da lista de Alt-Tab. Você também deve definir a propriedade ShowInTaskbar sua própria forma como falsa. O melhor de tudo, ele simplesmente não importa que estilo seu formulário principal tem, e todos os ajustes para realizar o esconderijo é apenas algumas linhas no código construtor.

Por que tentar tanto códigos? Basta definir a propriedade FormBorderStyle para FixedToolWindow. Espero que ajude.

vê-lo: (a partir 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);

Em XAML definir 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>

Edit:. Isso mostra Ainda em Alt + Tab Eu acho que, não apenas na barra de tarefas

Eu tentei configuração de visibilidade do formulário principal para false sempre que ele é automaticamente alterada para true:

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

Ele funciona perfeitamente:)

Do not mostrar um formulário. Use invisibilidade.

Mais aqui: http://code.msdn.microsoft.com/TheNotifyIconExample

Form1 Propriedades:
FormBorderStyle: Sizable
WindowState: minimizado
ShowInTaskbar: Falso

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

Se você deseja que o formulário para ser sem fronteiras, então você precisa adicionar as seguintes instruções para o construtor do formulário:

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

E você deve adicionar o seguinte método para a classe forma derivada:

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

mais detalhes

Pessoalmente, tanto quanto eu sei que isso não é possível sem enganchando em janelas de alguma forma, eu nem tenho certeza de como isso seria feito ou se é possível.

Dependendo de suas necessidades, desenvolvimento de seu contexto de aplicação como uma aplicação NotifyIcon (bandeja do sistema) vai permitir que ele seja correndo sem mostrar em ALT + TAB. Entretanto, se você abrir um formulário, que forma irá ainda seguem a funcionalidade padrão.

Eu posso escavar meu blog artigo sobre a criação de um aplicativo que é apenas uma NotifyIcon por padrão se quiser.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top