Melhor maneira de esconder uma janela do programa switcher Alt-Tab?
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.
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:
- para adicionar o
WS_EX_TOOLWINDOW
estendido estilo da janela -. Essa é a abordagem correta ??li> - 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 ??li>
- 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;
}
}
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.