Alt-Tab 프로그램 전환기에서 창을 숨기는 가장 좋은 방법은 무엇입니까?
나는 몇 년 동안 .NET 개발자로 일해 왔으며 이것은 여전히 내가 제대로하는 방법을 모르는 것들 중 하나입니다. Windows Forms 및 WPF의 속성을 통해 작업 표시 줄에서 창을 숨기는 것은 쉽지만 내가 알 수있는 한 Alt+ ↹Tab대화 상자 에서 숨겨지는 것을 보장하거나 영향을 미치지는 않습니다 . 나는 본 적이 보이지 않는 창에 표시 Alt+ ↹Tab, 난 그냥하는 창을 보장하는 가장 좋은 방법이 무엇인지 궁금하네요 결코 에 (표시 여부) 표시되지 Alt+의 ↹Tab대화.
업데이트 : 아래 게시 된 솔루션을 참조하십시오. 내 답변을 해결책으로 표시 할 수는 없지만 지금까지 작동하는 유일한 답변입니다.
업데이트 2 : 이제 꽤 괜찮아 보이지만 직접 시도하지는 않은 Franci Penov의 적절한 솔루션이 있습니다. 일부 Win32를 포함하지만 화면 밖의 창을 제대로 생성하지 않습니다.
최신 정보:
@donovan에 따르면 현대 WPF는 설정 ShowInTaskbar="False"
및 Visibility="Hidden"
XAML을 통해 기본적으로이를 지원합니다 . (아직 테스트하지 않았지만 그럼에도 불구하고 댓글 가시성을 높이기로 결정했습니다)
원래 답변 :
Win32 API의 작업 전환기에서 창을 숨기는 방법에는 두 가지가 있습니다.
WS_EX_TOOLWINDOW
확장 된 창 스타일 을 추가하는 것이 올바른 방법입니다.- 다른 창의 자식 창으로 만듭니다.
안타깝게도 WPF는 Win32처럼 창 스타일에 대한 유연한 제어를 지원하지 않습니다. 따라서 창이있는 창 WindowStyle=ToolWindow
은 기본 WS_CAPTION
및 WS_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=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+ 에서 숨겨야하는 앱의 모든 창에 재사용 할 수 있다고 가정합니다 ↹Tab.
Update: Ok so what I did was move the above code, minus the this.Owner = w
bit (and moving w.Hide()
immediately after w.Show()
, which works fine) into my application's constructor, creating a public static Window
called OwnerWindow
. Whenever I want a window to exhibit this behavior, I simply set this.Owner = App.OwnerWindow
. Works great, and only involves creating one extra (and invisible) window. You can even set this.Owner = null
if you want the window to reappear in the Alt+↹Tab dialog.
Thanks to Ivan Onuchin over on MSDN forums for the solution.
Update 2: You should also set ShowInTaskBar=false
on w
to prevent it from flashing briefly in the taskbar when shown.
Why so complex? Try this:
me.FormBorderStyle = FormBorderStyle.SizableToolWindow
me.ShowInTaskbar = false
Idea taken from here:http://www.csharp411.com/hide-form-from-alttab/
Here's what does the trick, regardless of the style of the window your are trying to hide from Alt+↹Tab.
Place the following into the constructor of your form:
// Keep this program out of the Alt-Tab menu
ShowInTaskbar = false;
Form form1 = new Form ( );
form1.FormBorderStyle = FormBorderStyle.FixedToolWindow;
form1.ShowInTaskbar = false;
Owner = form1;
Essentially, you make your form a child of an invisible window which has the correct style and ShowInTaskbar setting to keep out of the Alt-Tab list. You must also set your own form's ShowInTaskbar property to false. Best of all, it simply doesn't matter what style your main form has, and all tweaking to accomplish the hiding is just a few lines in the constructor code.
Why trying so much codes? Just set the FormBorderStyle
propety to FixedToolWindow
. Hope it helps.
see it:(from 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);
In XAML set 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: That still shows it in Alt+Tab I guess, just not in the taskbar.
I tried setting the main form's visibility to false whenever it is automatically changed to true:
private void Form1_VisibleChanged(object sender, EventArgs e)
{
if (this.Visible)
{
this.Visible = false;
}
}
It works perfectly :)
Don't show a form. Use invisibility.
More here: http://code.msdn.microsoft.com/TheNotifyIconExample
Form1 Properties:
FormBorderStyle: Sizable
WindowState: Minimized
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;
}>
if you want the form to be borderless, then you need to add the following statements to the form’s constructor:
this.FormBorderStyle = FormBorderStyle.None;
this.ShowInTaskbar = false;
AND you must add the following method to your derived Form class:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
// turn on WS_EX_TOOLWINDOW style bit
cp.ExStyle |= 0x80;
return cp;
}
}
Personally as far as I know this is not possible without hooking into windows in some fashion, I'm not even sure how that would be done or if it is possible.
Depending on your needs, developing your application context as a NotifyIcon (system tray) application will allow it to be running without showing in ALT + TAB. HOWEVER, if you open a form, that form will still follow the standard functionality.
I can dig up my blog article about creating an application that is ONLY a NotifyIcon by default if you want.
'development' 카테고리의 다른 글
표 셀에서 확인란을 중앙에 배치하는 방법은 무엇입니까? (0) | 2020.08.28 |
---|---|
사용시기 (0) | 2020.08.28 |
"스핀 락"이란 정확히 무엇입니까? (0) | 2020.08.28 |
int를 16 진수 문자열로 (0) | 2020.08.28 |
줄 바꿈이있는 유닉스 변수에 파일 내용 (0) | 2020.08.28 |