Alt-Tab プログラム スイッチャーからウィンドウを非表示にする最良の方法は?

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

  •  21-08-2019
  •  | 
  •  

質問

私は .NET 開発者になってから数年になりますが、これはまだ適切な方法を知らないものの 1 つです。Windows フォームと WPF の両方でプロパティを使用してタスク バーからウィンドウを非表示にするのは簡単ですが、私の知る限り、これはウィンドウがタスク バーから非表示になることを保証するものではありません (または必ずしも影響を与えることさえありません)。 代替+↹タブ ダイアログ。私は見た 見えない ウィンドウが表示されるのは 代替+↹タブ, 、ウィンドウが確実に機能することを保証する最善の方法は何だろうと考えています。 一度もない に表示されます (表示されるかどうかに関係なく) 代替+↹タブ ダイアログ。

アップデート: 以下の私が投稿した解決策を参照してください。自分の答えを解決策としてマークすることはできませんが、今のところ機能するのはこれだけです。

更新 2: Franci Penov による適切な解決策があり、かなり良さそうですが、私自身は試していません。一部の Win32 が含まれますが、オフスクリーン ウィンドウの不完全な作成を回避します。

役に立ちましたか?

解決

アップデート:

@donovan 氏によると、最近の WPF は設定を通じてこれをネイティブにサポートしています。ShowInTaskbar="False" そして Visibility="Hidden" XAML で。(まだテストしていませんが、コメントの可視性を高めることにしました)

元の答え:

Win32 API のタスク スイッチャーからウィンドウを非表示にする方法は 2 つあります。

  1. を追加するには WS_EX_TOOLWINDOW 拡張ウィンドウ スタイル - それが正しいアプローチです。
  2. 別のウィンドウの子ウィンドウにします。

残念ながら、WPF は Win32 ほど柔軟なウィンドウ スタイルの制御をサポートしていません。 WindowStyle=ToolWindow 結局デフォルトのままになる WS_CAPTION そして WS_SYSMENU スタイルにより、キャプションと閉じるボタンが表示されます。一方、次の設定を行うことで、これら 2 つのスタイルを削除できます。 WindowStyle=None, ただし、これでは設定されません WS_EX_TOOLWINDOW 拡張スタイルを使用すると、ウィンドウはタスク スイッチャーから非表示になりません。

WPF ウィンドウを使用するには WindowStyle=None これもタスク スイッチャーからは非表示になります。次の 2 つの方法のいずれかを実行できます。

  • 上記のサンプル コードを使用して、ウィンドウを小さな隠しツール ウィンドウの子ウィンドウにします。
  • ウィンドウ スタイルを変更して、 WS_EX_TOOLWINDOW 拡張スタイル。

私は個人的には 2 番目のアプローチの方が好きです。繰り返しになりますが、クライアント領域のガラスを拡張したり、キャプションでの 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 Windows XP の user32.dll にはエントリ ポイントが見つからないため、 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. 。非常にうまく機能し、追加の (そして非表示の) ウィンドウを 1 つ作成するだけです。設定することもできます this.Owner = null ウィンドウを再び表示したい場合は、 代替+↹タブ ダイアログ。

解決策については、MSDN フォーラムの Ivan Onuchin に感謝します。

更新 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;

基本的に、フォームを、Alt-Tab リストから除外するための正しいスタイルと ShowInTaskbar 設定を持つ非表示ウィンドウの子にします。また、独自のフォームの 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 ではまだ表示されますが、タスクバーには表示されないだけです。

メインフォームの可視性が自動的に true に変更されるたびに false に設定してみました。

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

完璧に動作します:)

フォームを表示しないでください。非表示を使用します。

詳細はこちら: http://code.msdn.microsoft.com/TheNotifyIconExample

Form1 のプロパティ:
フォームボーダースタイル:かなりの
ウィンドウ状態:最小化
タスクバーで表示:間違い

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