【问题标题】:Hide window from program switcher in NW.JS在 NW.JS 中从程序切换器中隐藏窗口
【发布时间】:2015-12-23 02:51:02
【问题描述】:

我正在使用 NW.JS (node-webkit) 编写桌面应用程序。在我的应用程序中,用户可能会打开许多​​窗口,我想将它们从程序切换器(alt+tab)和任务栏中隐藏起来。我已经找到了从任务栏隐藏窗口的选项,但找不到任何方法从程序切换器中隐藏它。甚至可能吗?或者至少可以将所有窗口归为一个(就像在 Windows 上的 Sticky Notes 中一样)?

【问题讨论】:

    标签: javascript node.js node-webkit nw.js


    【解决方案1】:

    这个功能可能会在某个时候出现,但从 0.12.3 版本开始,node-webkit 不提供任何用于实现工具类型窗口的接口,因此无法使用 javascript 或使用项目的包来实现这一点。 json 文件。我可以在这里想到两个选项。

    1. 自己构建 node-webkit。 The guide 非常直接和全面。需要修改native_aurora_aura.ccNativeWindowAura的构造函数,具体是这个位:

    #if defined(OS_WIN)
      HWND hwnd = views::HWNDForWidget(window_->GetTopLevelWidget());
      int current_style = ::GetWindowLong(hwnd, GWL_STYLE);
      ::SetWindowLong(hwnd, GWL_STYLE, current_style | WS_CAPTION); //This is the importante line
    #endif
    

    到:

      ::SetWindowLong(hwnd, GWL_STYLE, current_style | WS_CAPTION | WS_EX_TOOLWINDOW);
    

    请注意,这是一个简单的解决方案,它将导致 所有 新窗口默认为工具样式,并且在切换窗口时不可见。使该功能可用于清单文件或window API 将需要对几个文件进行更改。

    2. 编写和部署一个启动应用程序,该应用程序加载您打包的项目(或您的项目文件夹),不断搜索具有特定标题的窗口并设置窗口样式。这是一个使用 c# 控制台应用程序的示例,但您也可以为此使用 c++ 或任何 .NET 语言:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Runtime.InteropServices;
    using System.Timers;
    using System.Diagnostics;
    
    namespace nw
    {
       class Program
       {
          const int GWL_EXSTYLE      = -0x14;
          const int WS_EX_APPWINDOW  = 0x40000;
          const int WS_EX_TOOLWINDOW = 0x80;
          const int WS_EX_COMPOSITED = 0x02000000;
    
          [DllImport("user32", CharSet = CharSet.Auto)]
          static extern int GetWindowLong(IntPtr hwnd, int index);
    
          [DllImport("User32.Dll")]
          static extern int SetWindowLong(IntPtr hwnd, int index, int newLong);
    
          [DllImport("user32.dll", CharSet = CharSet.Unicode)]
          static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
    
          [DllImport("user32.dll", CharSet = CharSet.Unicode)]
          static extern int GetWindowTextLength(IntPtr hWnd);
    
          [DllImport("user32.dll")]
          static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
    
          [DllImport("user32.dll")]
          static extern IntPtr SetWindowText(IntPtr HWND, string Text);
    
          delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
    
    
          //------------------------------------------------------------------
          static void Main(string[] args)
          {
             // Test an unpackaged app like:
             // Process.Start(<path\to\nw.exe>, <path\to\project-folder>);
    
             Process.Start("packaged-nw-app.js");
    
             Timer timer = new Timer() { Interval = 100, Enabled = true };
             timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
    
             Console.ReadLine();
          }
    
    
          //------------------------------------------------------------------
          static void OnTimedEvent(object source, ElapsedEventArgs e)
          {
             // Find our target windows (change "nw-tool-window" to your window title)
             IEnumerable<IntPtr> windows = FindWindowsWithText("nw-tool-window");
    
             foreach (var window in windows)
             {
                // Apply WS_EX_TOOLWINDOW to the current style
                SetWindowLong(window, GWL_EXSTYLE, (GetWindowLong(window, GWL_EXSTYLE) | WS_EX_TOOLWINDOW) & ~WS_EX_APPWINDOW);
                // Change title to flag as changed
                SetWindowText(window, "nw-tool-window-hidden");
             }
          }
    
    
          //------------------------------------------------------------------
          static string GetWindowText(IntPtr hwnd)
          {
             int size = GetWindowTextLength(hwnd);
    
             if (size > 0)
             {
                var builder = new StringBuilder(size + 1);
                GetWindowText(hwnd, builder, builder.Capacity);
                return builder.ToString();
             }
    
             return String.Empty;
          }
    
    
          //------------------------------------------------------------------
          static IEnumerable<IntPtr> FindWindows(EnumWindowsProc filter)
          {
             IntPtr found = IntPtr.Zero;
             List<IntPtr> windows = new List<IntPtr>();
    
             EnumWindows(delegate(IntPtr wnd, IntPtr param)
             {
                if (filter(wnd, param))
                {
                   windows.Add(wnd);
                }
    
                return true;
             }, IntPtr.Zero);
    
             return windows;
          }
    
    
          //------------------------------------------------------------
          static IEnumerable<IntPtr> FindWindowsWithText(string titleText)
          {
             return FindWindows(delegate(IntPtr wnd, IntPtr param)
             {
                return GetWindowText(wnd).Contains(titleText);
             });
          } 
       }
    }
    

    查找标题的代码取自here。如果你只对你的主窗口感兴趣,你可以去掉上面的大部分代码,只使用FindWindowSetWindowLong。您还应该隐藏控制台或窗口(如果您使用 Forms 或 WPF 执行此操作),有足够的信息说明如何在 SO 上完成此操作。

    第二种方法有点老套,不过,我宁愿选择第一种。并且可能正确地实现它而不是硬编码并打开一个拉取请求:)

    【讨论】:

    • 谢谢,这似乎是实现它的方式。我会看看我今天是否有时间尝试一下。如果我想出一个好的解决方案,我会提出一个拉取请求,因为通过他们的 API 拥有这个功能真的很不错。
    【解决方案2】:

    我从未使用过 NW.JS,所以这可能是完全错误的,但看起来 NM.JS 有一个 Native UI 模块。我想使用这个模块你应该能够创建本地窗口并给它们一个 WS_EX_TOOLWINDOW 样式。请参阅此答案:Best way to hide a window from the Alt-Tab program switcher。如果您只针对 Windows,这似乎是通知的最佳途径。

    另一个需要考虑的想法是使用 IFRAMES 构建您的应用程序,以便只有一个本机窗口。然后您可以使用 javascript 和您自己的界面来决定显示哪些 IFRAMES。

    【讨论】:

      猜你喜欢
      • 2018-01-31
      • 2022-01-21
      • 1970-01-01
      • 2019-01-05
      • 1970-01-01
      • 2016-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多