C#从任务栏隐藏应用程序

时间:2011-11-23 14:10:13

标签: c# pinvoke spy++

我一直在努力从我的应用程序中隐藏任务栏中的另一个应用程序 我一直在使用SetWindowLong函数来设置/删除extended style上的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,但随机还有其他属性消失等。
在查看消息时,我还看到DID收到STYLE_CHANGED等消息。

任何帮助将不胜感激,

4 个答案:

答案 0 :(得分:4)

MSDN记录了确定哪些窗口在任务栏上有按钮的规则。 Raymond Chen给出了以下summary这些规则:

  

窗口进入任务栏有一些基本规则。在   短:

     
      
  • 如果设置了WS_EX_APPWIND扩展样式,则会显示(当可见时)。
  •   
  • 如果窗口是顶级无主窗口,则会显示(当可见时)。
  •   
  • 否则它不会显示。
  •   

您尝试修改另一个应用中的窗口这一事实严重阻碍了您。您正在删除WS_EX_APPWINDOW扩展样式。这还不够,因为有问题的窗口将是一个顶级的无主窗口(见第2点)。创建窗口后,您无法更改窗口的所有者,并且由于窗口由另一个窗口控制,您几乎被卡住了。

剩下的唯一选择是删除WS_EX_APPWINDOW扩展样式并将其替换为WS_EX_TOOLWINDOW。这确实会使窗口脱离任务栏,但会改变appearance of the window

  

该窗口旨在用作浮动工具栏。工具窗口   标题栏比普通标题栏短,而且标题栏比标准栏短   窗口标题使用较小的字体绘制。工具窗口没有   出现在任务栏或用户出现的对话框中   按ALT + TAB。如果工具窗口具有系统菜单,则其图标不是   显示在标题栏上。但是,您可以显示系统菜单   通过右键单击或键入ALT + SPACE。

答案 1 :(得分:3)

我是这样做的。

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 property的文档,它说“顶级窗口不能拥有所有者”。它应与此完全相反,只有顶级窗口才能拥有所有者!

答案 2 :(得分:2)

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位机器。

答案 3 :(得分:1)

有关您正在尝试执行的操作的详细信息,请参阅this StackOverflow answer的已接受答案。请特别注意有关安全性和线程的警告。