2015-09-25 24 views
12

Sto scrivendo un'applicazione desktop con NW.JS (node-webkit). Nella mia applicazione l'utente può aprire molte finestre e mi piacerebbe nasconderle dal programma di selezione (alt + tab) e dalla barra delle applicazioni. Ho già trovato l'opzione per nascondere la finestra da taksbar, ma non riesco a trovare alcun modo per nasconderla dal programma di commutazione. È possibile? O almeno è possibile raggruppare tutte le finestre come una (proprio come in Sticky Notes su Windows)?Nascondere la finestra dal programma di commutazione in NW.JS

risposta

0

Non ho mai usato NW.JS, quindi questo potrebbe essere completamente sbagliato, ma sembra che ci sia un modulo Native UI per NM.JS. Immagino che usando questo modulo dovresti essere in grado di creare finestre native e dare loro uno stile WS_EX_TOOLWINDOW. Vedi questa risposta: Best way to hide a window from the Alt-Tab program switcher. Questo sembra essere il miglior percorso per le notifiche se stai mirando solo a Windows.

Un'altra cosa da pensare è creare l'applicazione utilizzando IFRAMES in modo che sia presente un'unica finestra nativa. Quindi puoi usare javascript e le tue interfacce per decidere quali IFRAMES stanno mostrando.

1

Questa funzionalità sarà probabilmente presente a un certo punto, ma dalla versione 0.12.3 node-webkit non fornisce alcuna interfaccia per l'implementazione di finestre di tipo di strumento, quindi non c'è modo di farlo con javascript o utilizzando il pacchetto del progetto .json file. Posso pensare a due opzioni qui.

1. Costruire node-webkit autonomamente. The guide è abbastanza semplice e completo. È necessario modificare il costruttore di NativeWindowAura in native_aurora_aura.cc, in particolare questo bit:

#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 

a:

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

Si noti che questa è una soluzione semplice che causerà tutti le nuove finestre di Default per strumento stile e non essere visibile quando si passa a Windows. Rendere questa funzionalità disponibile per il file manifest o window API richiederebbe modifiche su un paio di altri file.

2. Scrivere e distribuire un'applicazione di avvio che carica il progetto in pacchetti (o la cartella del progetto), ricerca continuamente finestre con un titolo specifico e imposta lo stile della finestra. Ecco un esempio utilizzando un C# applicazione console, ma è possibile utilizzare anche usare C++ o qualsiasi altro linguaggio .NET per questo:

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

Il codice per trovare il titolo è stato preso da here. Se sei interessato solo alla tua finestra principale, puoi eliminare la maggior parte del codice qui sopra e farla franca solo usando FindWindow e SetWindowLong. Probabilmente dovresti anche nascondere la console o la finestra (se lo fai con Forms o WPF), ci sono abbastanza informazioni su come ottenerlo su SO.

Il secondo approccio è un po 'hacky, però, preferirei andare con il primo. E magari implementarlo correttamente invece di codificare e aprire una richiesta pull :)

+1

Grazie, questo sembra il modo di implementarlo. Vedrò se riesco a trovare il tempo per provarlo oggi. Se trovo una buona soluzione, farò una richiesta di pull, poiché questa caratteristica sarebbe davvero piacevole da avere attraverso la loro API. – thebreiflabb