Подтвердить что ты не робот

Скрыть окно из программного переключателя в NW.JS

Я пишу настольное приложение с NW.JS(node -webkit). В моем приложении пользователь может открыть много окон, и я хотел бы скрыть их от программного переключателя (alt + tab) и панели задач. Я уже нашел вариант скрыть окно от taksbar, но не могу найти способ скрыть его от программного переключателя. Возможно ли это? Или, по крайней мере, можно сгруппировать все окна как одно (как в Sticky Notes для Windows)?

4b9b3361

Ответ 1

Эта функция, вероятно, будет присутствовать в какой-то момент, но с версии 0.12.3 node -webkit не предоставляет никакого интерфейса для реализации окон типа инструмента, поэтому нет возможности выполнить это с помощью javascript или с помощью проекта package.json файл. Я могу придумать здесь два варианта.

1. Создайте node -webkit самостоятельно. Руководство довольно прямолинейно и полно. Вам нужно изменить конструктор NativeWindowAura в native_aurora_aura.cc, в частности этот бит:

#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);

Обратите внимание, что это простое решение, которое приведет к появлению новых всех новых окон по умолчанию в стиле инструмента и не будет отображаться при переключении окон. Чтобы эта функция была доступна для файла манифеста или API окна, потребуются изменения еще на пару файлов.

2. Запишите и разверните приложение запуска, которое загружает ваш упакованный проект (или папку вашего проекта), постоянно ищет окна с определенным заголовком и задает стиль окна. Вот пример использования консольного приложения С#, но вы можете использовать также С++ или любой язык .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);
         });
      } 
   }
}

Код для поиска названия принимался из здесь. Если вас интересует только ваше главное окно, вы можете избавиться от большей части приведенного выше кода и уйти, просто используя FindWindow и SetWindowLong. Вероятно, вы также должны скрыть консоль или окно (если вы делаете это с помощью форм или WPF), достаточно информации о том, как это сделать на SO.

Второй подход немного взломан, хотя я бы предпочел перейти к первому. И, возможно, реализовать его правильно, а не жестко запрограммировать и открыть запрос на перенос:)

Ответ 2

Я никогда не использовал NW.JS, так что это может быть совершенно неправильно, но похоже, что есть Собственный интерфейс для NM.JS. Я бы предположил, что с помощью этого модуля вы сможете создавать собственные окна и давать им стиль WS_EX_TOOLWINDOW. См. Этот ответ: Лучший способ скрыть окно из переключателя программ Alt-Tab. Это лучший путь для уведомлений, если вы ориентируетесь только на Windows.

Еще подумаем, что нужно создать ваше приложение, используя IFRAMES, чтобы было только одно собственное окно. Затем вы можете использовать javascript и свои собственные интерфейсы, чтобы определить, какие IFRAMES показываются.