从任务栏隐藏应用程序
本文关键字:应用程序 隐藏 任务栏 | 更新日期: 2023-09-27 18:15:44
我一直在努力从应用程序的任务栏中隐藏另一个应用程序
我一直在使用SetWindowLong函数来设置/删除扩展样式上的WS_EX_APPWINDOW
。
我已经尝试过分别设置和删除属性,以及获取当前的WindowLong
,并将其删除/添加到该属性中,如下所示:
SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow) & WS_EX_APPWINDOW);
并尝试这样删除它:
SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow) & ~WS_EX_APPWINDOW);
还尝试了这两种方法,但都没有先让窗口变长。这是我的全部代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
[DllImport("User32.dll")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("User32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
private const int SW_HIDE = 0x00;
private const int SW_SHOW = 0x05;
private const int WS_EX_APPWINDOW = 0x40000;
private const int GWL_EXSTYLE = -0x14;
private void HideWindowFromTaskbar(IntPtr pMainWindow)
{
SetWindowLong(pMainWindow, GWL_EXSTYLE, ~WS_EX_APPWINDOW);
ShowWindow(pMainWindow, SW_HIDE);
ShowWindow(pMainWindow, SW_SHOW);
}
private void ButtonHide_Click(object sender, RoutedEventArgs e)
{
HideWindowFromTaskbar(Process.GetProcessesByName("notepad")[0].MainWindowHandle);
}
}
我注意到Spy++在查看属性时发生了变化。我得到了一堆不同的结果,比如添加了WS_EX_APPWINDOW
,但也随机地有其他属性消失,等等。
在查看这些消息时,我还发现它确实收到了类似STYLE_CHANGED
的消息。
MSDN上记录了确定哪些窗口的任务栏上有按钮的规则。Raymond Chen对这些规则进行了以下总结:
窗口进入任务栏的基本规则如下。在里面short:
- 如果设置了WS_EX_APPWINDOW扩展样式,则它将显示(当可见时(
- 如果该窗口是顶级无主窗口,则它将显示(当可见时(
- 否则就不会显示
事实上,你正试图修改另一个应用程序中的窗口,这严重阻碍了你。您正在删除WS_EX_APPWINDOW
扩展样式。这还不够,因为有问题的窗口将是一个顶级无主窗口(请参见项目符号2(。一旦创建了一个窗口,就不能更改它的所有者,而且由于该窗口由另一个进程控制,所以您几乎陷入了困境。
剩下的唯一选项是删除WS_EX_APPWINDOW
扩展样式并将其替换为WS_EX_TOOLWINDOW
。这确实会使窗口从任务栏上消失,但它会改变窗口的外观:
该窗口旨在用作浮动工具栏。工具窗口具有比正常标题栏短的标题栏,并且窗口标题使用较小的字体绘制。工具窗口不会出现在任务栏或用户按ALT+TAB。如果工具窗口有系统菜单,则其图标不是显示在标题栏上。但是,您可以显示系统菜单通过右键单击或键入ALT+SPACE。
以下是我的操作方法。
1. Create a window (hwndOwner) with WS_POPUP style and WS_EX_TOOLWINDOW
2. Call SetWindowLong(hwnd, GWL_HWNDPARENT, hwndOwner)
3. Call SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | ~WS_EX_APPWINDOW)
这将从任务栏和alt选项卡中删除目标窗口。这将至少适用于自WS2000以来的每个操作系统。
现在,David Heffernan指出MSDN文档中说你不能这样做。嗯,我不知道它为什么这么说,但它不准确。你可以做到这一点,而INFACT.NET Framework也可以做到这,只需使用.NET Reflector来检查System.Windows.Forms.Form.Owner属性的代码-它使用SetWindowLong来转移所有权,只要你愿意!
关于MSDN文档不正确的更多证据,只需看看Owner属性的文档,它说"顶级窗口不能有所有者"。它应该与此完全相反,只有顶级窗口才能有所有者
private const int SW_HIDE = 0x00;
private const int SW_SHOW = 0x05;
private const int WS_EX_APPWINDOW = 0x40000;
private const int GWL_EXSTYLE = -0x14;
private const int WS_EX_TOOLWINDOW = 0x0080;
private static void HideAppinTaskBar()
{
var Handle = FindWindowByCaption(IntPtr.Zero, "Untitled - Notepad");
ShowWindow(Handle, SW_HIDE);
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_TOOLWINDOW);
ShowWindow(Handle, SW_SHOW);
}
这对我有用——用记事本测试过。WinXp 32位机器。
这在WinUI3中与PInvoke.User32nuget软件包在.NET 6.0上运行:
改编自亚历克斯的回答。
private void HideAppFromTaskBar(MainWindow window)
{
//Get the Window's HWND
var windowNative = window.As<IWindowNative>();
var windowHandle = windowNative.WindowHandle;
User32.ShowWindow(windowHandle, User32.WindowShowStyle.SW_HIDE);
var flags = (User32.SetWindowLongFlags)User32.GetWindowLong(windowHandle, User32.WindowLongIndexFlags.GWL_EXSTYLE);
User32.SetWindowLong(windowHandle, User32.WindowLongIndexFlags.GWL_EXSTYLE, flags | User32.SetWindowLongFlags.WS_EX_TOOLWINDOW);
User32.ShowWindow(windowHandle, User32.WindowShowStyle.SW_SHOW);
}