Alt-Tab 프로그램 전환기에서 창을 숨기는 가장 좋은 방법은 무엇입니까?


101

나는 몇 년 동안 .NET 개발자로 일해 왔으며 이것은 여전히 ​​내가 제대로하는 방법을 모르는 것들 중 하나입니다. Windows Forms 및 WPF의 속성을 통해 작업 표시 줄에서 창을 숨기는 것은 쉽지만 내가 알 수있는 한 Alt+ ↹Tab대화 상자 에서 숨겨지는 것을 보장하거나 영향을 미치지는 않습니다 . 나는 본 적이 보이지 않는 창에 표시 Alt+ ↹Tab, 난 그냥하는 창을 보장하는 가장 좋은 방법이 무엇인지 궁금하네요 결코 에 (표시 여부) 표시되지 Alt+의 ↹Tab대화.

업데이트 : 아래 게시 된 솔루션을 참조하십시오. 내 답변을 해결책으로 표시 할 수는 없지만 지금까지 작동하는 유일한 답변입니다.

업데이트 2 : 이제 꽤 괜찮아 보이지만 직접 시도하지는 않은 Franci Penov의 적절한 솔루션이 있습니다. 일부 Win32를 포함하지만 화면 밖의 창을 제대로 생성하지 않습니다.


13
시스템 트레이 앱이 좋은 예입니다
TravisO

3
내 앱이 UAC 대화 상자와 같은 모달 인터페이스를 표시 할 때 "디밍"효과를 제공하기 위해 전체 화면 반투명 검정색 창을 사용하기 때문에 한 가지 이유가 있습니다. 이것은 대화 형 창이 아니기 때문에 Alt-Tab 대화 상자에 표시 할 필요가 없습니다.
devios1

8
앱이 자체 모달 대화 상자를 표시 할 때 전체 데스크톱을 어둡게하지 않는 것이 좋습니다. 바탕 화면을 어둡게하면 OS 수준 작동을 제안합니다. 대부분의 사람들은 안전한 데스크톱이 아니라는 것을 이해할 수있을만큼 충분한 지식을 얻지 못했을 것입니다.
Franci Penov

3
"속성을 통해 작업 표시 줄에서 창을 숨기는 것은 쉽습니다." 이 속성은 ShowInTaskbar입니다 (레코드 용).
greenoldman 2010 년

문제는 작업 표시 줄이 아닌 Alt-Tab에서 창을 숨기는 것입니다.
Alexandru Dicu

답변:


93

최신 정보:

@donovan에 따르면 현대 WPF는 설정 ShowInTaskbar="False"Visibility="Hidden"XAML을 통해 기본적으로이를 지원합니다 . (아직 테스트하지 않았지만 그럼에도 불구하고 댓글 가시성을 높이기로 결정했습니다)

원래 답변 :

Win32 API의 작업 전환기에서 창을 숨기는 방법에는 두 가지가 있습니다.

  1. WS_EX_TOOLWINDOW확장 된 창 스타일 을 추가하는 것이 올바른 방법입니다.
  2. 다른 창의 자식 창으로 만듭니다.

안타깝게도 WPF는 Win32처럼 창 스타일에 대한 유연한 제어를 지원하지 않습니다. 따라서 창이있는 창 WindowStyle=ToolWindow은 기본 WS_CAPTIONWS_SYSMENU스타일 로 끝납니다 . 이로 인해 캡션과 닫기 버튼이 있습니다. 반면을 설정하여이 두 가지 스타일을 제거 할 수 WindowStyle=None있지만 WS_EX_TOOLWINDOW확장 된 스타일이 설정 되지 않고 창이 작업 전환기에서 숨겨지지 않습니다.

WindowStyle=None작업 전환기에서도 숨겨 지는 WPF 창을 가지려면 다음 두 가지 방법 중 하나를 사용할 수 있습니다.

  • 위의 샘플 코드를 사용하여 창을 작은 숨겨진 도구 창의 자식 창으로 만듭니다.
  • WS_EX_TOOLWINDOW확장 된 스타일 도 포함하도록 창 스타일을 수정합니다 .

개인적으로 두 번째 접근 방식을 선호합니다. 그런 다음 클라이언트 영역에서 유리를 확장하고 어쨌든 캡션에서 WPF 그리기를 활성화하는 것과 같은 고급 작업을 수행하므로 약간의 상호 운용성은 큰 문제가 아닙니다.

다음은 Win32 interop 솔루션 접근 방식에 대한 샘플 코드입니다. 먼저 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=NoneShowInTaskbar=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 interop 선언. 샘플 코드를 작게 유지하기 위해 열거 형에서 불필요한 스타일을 모두 제거했습니다. 또한 불행히도 SetWindowLongPtrWindows 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

2
이것을 확인하지 않았지만 당신이 말하는 것을 아는 것 같습니다. :) 다시해야 할 경우 이것을 염두에 두겠습니다.하지만 다른 솔루션이 잘 작동하기 때문에 (그리고이 책에 대한 책을 닫은 지 한참이 지났습니다) 나는 뭔가를 망치고 깨뜨리고 싶지 않습니다. . 감사!
devios1

1
완벽하게 작동합니다! 감사!
Anthony Brien

나를 위해 잘 작동합니다. 그러나 나는 다음과 같이 dll을 가져와야하는 것을 싫어한다 : P
J4N

8
@ J4N - :-) 땐 P / 호출의 비트와 함께이의 아무것도 잘못
FRANCI Penov

1
이것은 WPF에서 나를 위해 작동하지 않았습니다. 하지만 놀아 본 후에는 XAML에서 ShowInTaskbar = "False"및 Visibility = "Hidden"을 설정하는 것이 훨씬 더 쉬운 해결책을 찾았습니다. 특별한 핀 보크가 필요하지 않습니다.
donovan

40

양식 클래스 안에 다음을 추가하십시오.

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

        return Params;
    }
}

그것만큼 쉽습니다. 매력을 발휘합니다!


3
이 작업을 수행하려면 ShowInTaskbar를 false로 설정해야합니다.
Nick Spreitzer 2013 년

20

해결책을 찾았지만 예쁘지 않습니다. 지금까지 이것이 실제로 작동 하는 유일한 시도입니다.

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 = null에 창이 다시 나타나도록 설정할 수도 있습니다 .Alt↹Tab

솔루션에 대한 MSDN 포럼의 Ivan Onuchin에게 감사드립니다.

업데이트 2 : 당신은 설정해야합니다 ShowInTaskBar=falsew표시 할 때 작업 표시 줄에서 잠시 깜박이는 것을 방지 할 수 있습니다.


이 문제에 대한 Win32 interop 솔루션도 있습니다.
Franci Penov

흥미롭게도이 접근 방식을 사용하고 있지만 숨겨진 창 (주 앱 창을 소유자로 사용)을 피하고 Alt-Tab에 표시되지 않습니다.
Dave

1
듀얼 모니터 구성에서 두 번째 화면도 음의 좌표를 가질 수 있다고 생각합니다.
Thomas Weller 2014

@ThomasW. 당신 말이 맞을 것입니다. 오프셋을 사용하는 -100000것이 아마도 더 좋을 것입니다.
devios1 2014

이것은이 문제에 대한 정말 나쁜 해킹입니다.
Alexandru Dicu


10

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;

기본적으로 양식을 올바른 스타일과 ShowInTaskbar 설정이있는 보이지 않는 창의 자식으로 만들어 Alt-Tab 목록에서 제외됩니다. 또한 사용자 양식의 ShowInTaskbar 속성을 false로 설정해야합니다. 무엇보다도 메인 폼의 스타일이 무엇인지는 중요하지 않으며, 숨김을 달성하기위한 모든 조정 작업은 생성자 코드에서 몇 줄이면됩니다.


잠깐 ... 이것은 C # 또는 C 또는 C ++ ??? 나는 정말 C 가족의 n00b입니다 ...
Sreenikethan I

3

왜 그렇게 많은 코드를 시도합니까? FormBorderStyle속성을로 설정하십시오 FixedToolWindow. 도움이되기를 바랍니다.


2

그것을 참조하십시오 :( 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);

여기에 'Handle'이 var handle = new WindowInteropHelper (this) .Handle에 의해 획득 될 수 있다고 추가합니다.
Alexandru Dicu

1

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에 여전히 표시됩니다.


예, 그게 문제입니다. ShowInTaskbar는 예상대로 Alt + Tab 대화 상자에 영향을주지 않습니다.
devios1

1

자동으로 true로 변경 될 때마다 기본 양식의 가시성을 false로 설정하려고했습니다.

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

완벽하게 작동합니다 :)


2
가장 쉬운 솔루션 일뿐만 아니라 저에게도 매우 잘 작동했습니다.
Daniel McQuiston

1

폼에 테두리가 없도록하려면 폼의 생성자에 다음 문을 추가해야합니다.

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

자세한 내용은



0

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

-1

개인적으로 내가 아는 한 어떤 방식으로 창문에 연결하지 않고는 이것이 가능하지 않다. 나는 그것이 어떻게 될지 또는 가능한지조차 확신하지 못한다.

필요에 따라 애플리케이션 컨텍스트를 NotifyIcon (시스템 트레이) 애플리케이션으로 개발하면 ALT + TAB에 표시되지 않고 실행될 수 있습니다. 그러나 양식을 열면 해당 양식은 여전히 ​​표준 기능을 따릅니다.

원하는 경우 기본적으로 NotifyIcon 만있는 응용 프로그램을 만드는 방법에 대한 내 블로그 기사를 찾아 볼 수 있습니다.



저는 이미 NotifyIcons에 정통합니다. 감사합니다. 문제는 Alt + Tab에서 열려있는 (비대화 형 또는 최상위) 창을 숨기고 싶다는 것입니다. 흥미롭게도 Vista 사이드 바가 Alt + Tab에 표시되지 않는다는 것을 알았습니다. 그래서 몇 가지 방법이 있어야합니다.
devios1

창 유형을 변경하지 않고 다양한 조각과 조각을 보면 (redbeard 게시 됨) 이렇게하는 방법을 모르겠습니다.
Mitchel Sellers
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.