2010-05-15 13 views
5

Ho un'applicazione C# winforms che viene eseguita in background, in attesa che vengano premuti i tasti di scelta rapida. Quando viene premuto un tasto di scelta rapida, la mia forma fa una breve apparizione. Il modulo è sempre in esecuzione, ma impostato su nascosto fino a quando non ricevo un evento hotkey, momento in cui imposto la proprietà visible su true. Il codice è simile al seguente:Come impedire alla mia applicazione Winforms C# di rubare lo stato attivo quando imposto correttamente il visibile su true?

void hook_volumeDown(object sender, KeyPressedEventArgs e) 
{ 
    this.Visible = true; 
} 

Si noti che la proprietà più in alto di questo modulo è impostata su true.

La parte davvero strana è che, dopo che la mia app C# ha rubato lo stato attivo da un'altra applicazione, non lo farà mai più. Ad esempio: avvio la mia app, quindi lancio alcune app fullscreep come Team Fortress 2. Quindi premo il mio tasto di scelta rapida. Team Fortress 2 minimizza e vedo la mia forma. Quindi, tuttavia, posso ripristinare TF2 e premere di nuovo il mio tasto di scelta rapida tutto ciò che desidero (con l'effetto desiderato) e TF2 rimarrà concentrato.

In ogni caso, sto cercando un modo per risolvere questo problema. Ho trovato un sacco di domande qui che trattano problemi simili, ma tutti sono legati alla creazione/al lancio di un nuovo modulo, non rendendo visibile uno esistente (a meno che non mi sia sfuggito qualcosa). Potrei rielaborare l'applicazione per creare un nuovo modulo ogni volta che ne ho bisogno, ma ciò implicherebbe la creazione di un altro modulo per essere sempre invisibile solo per aspettare gli eventi hotkey, quindi preferirei lasciarlo così com'è.

Qualche idea?

+0

Non sono sicuro che seguo ... stai dicendo che funziona come dovrebbe * tranne * per la prima volta? –

risposta

6

Penso che il tuo problema sia legato al fatto che Visible = true si comporta in modo diverso tra la prima e le successive chiamate. Viene chiamata la prima volta visibile e l'handle della finestra non è stato creato, la finestra viene creata chiamando CreateWindowEx che ha alcuni parametri di stile che controllano il comportamento della finestra. Penso che sia necessario assicurarsi che la finestra venga creata con lo stile WS_EX_NOACTIVATE, che è possibile eseguire sovrascrivendo CreateParams.

Altre cose da provare:

1) La funzione ShowWindow (usato da Visible = true) ignora il parametro fuoco la prima volta che viene chiamato (http://msdn.microsoft.com/en-us/library/ms633548%28VS.85%29.aspx) se il programma prevede una struttura STARTUPINFO. Scava nel riflettore e scopri se la classe Form fornisce una struttura STARTUPINFO e, in tal caso, come manipolarla.

2) Il modulo ha una proprietà ShowWithoutActivation che può essere ignorata e impostata su true, hai sovrascritto questo?

Ci scusiamo per la "risposta inesatta", ma spero che questo vi fornisca almeno alcuni punti di partenza per ulteriori indagini. In bocca al lupo.

+1

Grazie, l'override di ShowWithoutActivation si è rivelata la soluzione perfetta. Una riga di codice e tutto è fisso. – Fopedush

+0

Overriding ShowWithout L'attivazione diventa IS la soluzione perfetta anche per me. – beppe9000

1

Vedere KeyPressedEventArgs in uso nella tua funzione sembra veramente strano. I tasti di scelta rapida possono essere implementati da P/Invocando la funzione API RegisterHotKey(). Invia un messaggio alla tua finestra quando viene premuto il tasto di scelta rapida. Ecco un esempio di una forma invisibile all'avvio, che si attiva quando premi il tasto di scelta rapida. Ctrl + Alt + U in questo caso:

using System; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

namespace WindowsFormsApplication1 { 
    public partial class Form1 : Form { 
     private const int MYKEYID = 0; // In case you want to register more than one... 
     public Form1() { 
      InitializeComponent(); 
      this.FormClosing += (s, args) => UnregisterHotKey(this.Handle, MYKEYID); 
     } 
     protected override void SetVisibleCore(bool value) { 
      if (value && !this.IsHandleCreated) { 
       this.CreateHandle(); 
       RegisterHotKey(this.Handle, MYKEYID, MOD_CONTROL + MOD_SHIFT, Keys.U); 
       value = false; 
      } 
      base.SetVisibleCore(value); 
     } 
     protected override void WndProc(ref Message m) { 
      if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == MYKEYID) { 
       this.Visible = true; 
       if (this.WindowState == FormWindowState.Minimized) 
        this.WindowState = FormWindowState.Normal; 
       SetForegroundWindow(this.Handle); 
      } 
      base.WndProc(ref m); 
     } 
     // P/Invoke declarations 
     private const int WM_HOTKEY = 0x312; 
     private const int MOD_ALT = 1; 
     private const int MOD_CONTROL = 2; 
     private const int MOD_SHIFT = 4; 
     [DllImport("user32.dll")] 
     private static extern int RegisterHotKey(IntPtr hWnd, int id, int modifier, Keys vk); 
     [DllImport("user32.dll")] 
     private static extern bool UnregisterHotKey(IntPtr hWnd, int id); 
     [DllImport("user32.dll")] 
     private static extern bool SetForegroundWindow(IntPtr hWnd); 
    } 
} 

Nota che la funzione SetForegroundWindow() è il punto debole, forse anche la fonte del problema che si descrive nella sua interrogazione. Windows non consente a un'app di spostare una finestra sul volto dell'utente quando l'utente utilizza attivamente un'altra finestra. Almeno alcuni secondi di inattività devono scadere prima che consenta alla finestra di rubare la messa a fuoco. Con il codice dato, che è abbastanza facile da vedere, il pulsante della barra delle applicazioni del tuo modulo lampeggerà. Evitare di impostare la proprietà ShowInTaskbar su false. Non è necessario farlo con questo codice, il pulsante della barra delle applicazioni non verrà visualizzato fino a quando non viene premuto il tasto di scelta rapida.

+0

Upvoting per la completezza della risposta, anche se non l'ho provato. Sto usando una classe wrapper per i tasti di scelta rapida che essenzialmente fa la stessa cosa che hai mostrato, quindi lancia un evento. Ai fini di questa app, è importante che la voce della barra delle applicazioni non sia stata mostrata, anche quando viene premuto il tasto di scelta rapida. – Fopedush

+0

Non riesco a vedere come abbia senso far perdere la finestra pop-up dietro una finestra in primo piano più grande senza che l'utente possa attivarla. Oh bene. –

+0

topmost è impostato su true, quindi a meno che non vi siano circostanze insolite (app a schermo intero), sarà visibile. La finestra funge da OSD per il volume di sistema, i miei tasti di scelta rapida si alzano/abbassano/disattivano. La forma è letteralmente solo una piccola cosa senza bordi con una barra di avanzamento e un'etichetta che mostra il volume%. – Fopedush

Problemi correlati