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

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

  •  21-08-2019
  •  | 
  •  

문제

저는 몇 년 동안 .NET 개발자로 활동해 왔지만 이 작업은 여전히 ​​제대로 수행하는 방법을 모르는 작업 중 하나입니다.Windows Forms와 WPF의 속성을 통해 작업 표시줄에서 창을 숨기는 것은 쉽지만, 제가 아는 한 이것이 창에서 숨겨지는 것을 보장하거나 반드시 영향을 미치는 것은 아닙니다. Alt+↹탭 대화.나는 본 적이 보이지 않는 창문이 에 나타난다 Alt+↹탭, 그리고 창문의 작동을 보장하는 가장 좋은 방법이 무엇인지 궁금합니다. 절대 표시(표시 여부) Alt+↹탭 대화.

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

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

도움이 되었습니까?

해결책

업데이트:

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

원래 답변:

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

  1. 추가하려면 WS_EX_TOOLWINDOW 확장 창 스타일 - 이것이 올바른 접근 방식입니다.
  2. 다른 창의 자식 창으로 만듭니다.

불행하게도 WPF는 Win32처럼 창 스타일에 대한 유연한 제어를 지원하지 않습니다. WindowStyle=ToolWindow 기본값으로 끝남 WS_CAPTION 그리고 WS_SYSMENU 캡션과 닫기 버튼이 있는 스타일입니다.반면에 다음을 설정하여 이 두 스타일을 제거할 수 있습니다. WindowStyle=None, 그러나 이렇게 하면 WS_EX_TOOLWINDOW 확장 스타일을 사용하면 창이 작업 전환기에서 숨겨지지 않습니다.

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

  • 위의 샘플 코드를 사용하여 창을 작은 숨겨진 도구 창의 하위 창으로 만듭니다.
  • 또한 포함하도록 창 스타일을 수정합니다. 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=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 interop 선언입니다.여기의 샘플 코드를 작게 유지하기 위해 열거형에서 불필요한 스타일을 모두 제거했습니다.또한, 불행하게도 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'를 생성하고 앱에서 숨겨야 하는 모든 창에 대해 이를 재사용할 수 있다고 가정합니다. Alt+↹탭.

업데이트: 좋습니다. 제가 한 일은 위의 코드를 이동한 것입니다. this.Owner = w 비트(그리고 이동 w.Hide() 직후 w.Show(), 잘 작동함)을 내 애플리케이션의 생성자에 추가하여 공개 정적을 생성합니다. Window ~라고 불리는 OwnerWindow.창에서 이 동작을 나타내기를 원할 때마다 간단히 설정합니다. this.Owner = App.OwnerWindow.훌륭하게 작동하며 추가(그리고 보이지 않는) 창을 하나만 생성하면 됩니다.설정할 수도 있습니다 this.Owner = null 창을 다시 표시하려면 Alt+↹탭 대화.

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

업데이트 2: 또한 설정해야합니다 ShowInTaskBar=false ~에 w 표시될 때 작업 표시줄에 잠시 깜박이는 것을 방지합니다.

왜 그렇게 복잡합니까?이 시도:

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

여기에서 가져온 아이디어 :http://www.csharp411.com/hide-form-from-alttab/

숨기려는 창의 스타일에 관계없이 트릭을 수행하는 방법은 다음과 같습니다. Alt+↹탭.

양식 생성자에 다음을 배치합니다.

// 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