2009-05-29 12 views
10

Devo gestire l'applicazione WPF prima che vada a ridurre, non quando è già lì. Ho trovato su Window oggetto StateChanged, ma si attiva quando l'oggetto Window è già in stato Minimize, quindi è troppo tardi.Window StateChanging event in WPF

Quindi, ho bisogno di qualcosa come evento "StateChanging" da gestire, mentre l'oggetto Finestra è ancora nello stato precedente.

È possibile creare tale evento?

risposta

11

Trovati messaggi di Windows richiamati nella finestra subito prima di ridurre al minimo l'utilizzo di Spy ++. Il primo che viene chiamato è WM_WINDOWPOSCHANGING. Non sapevo che Windows si muovesse sulla finestra -32000, -32000 punto di localizzazione quando si minimizzava la vedova, e quelli erano i parametri in WM_WINDOWPOSCHANGING. Tuttavia, ho provato solo su Vista. Codice http://blogs.msdn.com/oldnewthing/archive/2004/10/28/249044.aspx

usata qui è stato pubblicato da Nir here

qui è il codice di esempio

XAML:

<Window x:Class="WindowStateTest2.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="300" Width="300"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"></RowDefinition> 

     <RowDefinition Height="*"></RowDefinition> 
    </Grid.RowDefinitions> 
     <Button Click="btnClear_Click" Grid.Row="0" x:Name="btnClear">Clear</Button>    

     <TextBox Name="txt" VerticalScrollBarVisibility="Visible" Grid.Row="2"></TextBox> 
</Grid> 
</Window> 

C#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Windows.Interop; 
using System.Runtime.InteropServices; 

namespace WindowStateTest2 
{ 
/// <summary> 
/// Interaction logic for Window1.xaml 
/// </summary> 
public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 

     this.StateChanged += new EventHandler(Window1_StateChanged); 
     this.SourceInitialized += new EventHandler(Window1_SourceInitialized); 

    } 

    #region Event handlers 

    void btnClear_Click(object sender, RoutedEventArgs e) 
    { 
     this.txt.Text = string.Empty; 
    } 
    void Window1_SourceInitialized(object sender, EventArgs e) 
    { 
     AttachWndProc(); 
    } 

    void Window1_StateChanged(object sender, EventArgs e) 
    { 
     if (this.WindowState == WindowState.Minimized) 
      Console.WriteLine("SC: " + this.WindowState); 
    } 

    #endregion 

    #region Const 

    private int SYSCOMMAND = 0x0112; 
    private int SC_MINIMIZE = 0xf020; 
    private int WINDOWPOSCHANGING = 0x0046; 

    #endregion 

    private void AttachWndProc() 
    { 
     HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); 
     source.AddHook(new HwndSourceHook(WndProc)); 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    internal struct WINDOWPOSPARAMS 
    { 
     public IntPtr hwnd; 
     public IntPtr hwndInsertAfter; 
     public int x; 
     public int y; 
     public int cx; 
     public int cy; 
     public int flags; 
    } 


    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
    { 
     if (msg == WINDOWPOSCHANGING)    
     { 
      WINDOWPOSPARAMS param = (WINDOWPOSPARAMS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOSPARAMS)); 
      if (param.x == -32000 && param.y == -32000) 
      { 
       Output(""); 

            // EVENT WOULD BE RAISED HERE 

       Output("State before minimize:"); 
       Output(string.Format("CurrentState: {0}", this.WindowState)); 
       Output(string.Format("Location {0} {1}: ", this.Top, this.Left)); 
       Output(""); 
      } 
     } 

     // process minimize button 
     if (msg == SYSCOMMAND && SC_MINIMIZE == wParam.ToInt32()) 
     { 
      Output("Minimize clicked");    
     } 

     handled = false; 
     return IntPtr.Zero; 
    } 

    public void Output(object output) 
    { 
     this.txt.Text += output.ToString(); 
     this.txt.Text += Environment.NewLine;   
    }  

} 
} 
0

Non penso che sarete in grado di farlo direttamente.

Una chiamata di minimizzazione alla finestra può verificarsi da un numero di punti, non solo il pulsante di ridimensionamento di Window Chrome (ad esempio, facendo clic con il pulsante destro del mouse su TaskBar o dal Task Manager di Windows) e AFAIK, non c'è modo di gestisci direttamente gli eventi del pulsante attivati ​​da Window Chrome (se qualcuno sa come farlo, faccelo sapere!).

è una buona notizia, ma non è banale, quindi dovrai decidere se ne vale la pena. Innanzitutto, dovrai sostituire la finestra standard di Chrome con la tua. Puoi scoprire come farlo here.

In secondo luogo, è necessario creare i propri pulsanti "Ingrandisci/Riduci/Chiudi" e cablare gli eventi ai comportamenti appropriati. Poiché questa è la tua interfaccia utente, sei libero di ascoltare e cancellare gli eventi Button come preferisci.

Ricorda che non sarai ancora in grado di rilevare o impedire agli utenti di ridurre a icona tramite TaskBar/Task Manager di Windows, quindi potrebbe non essere esattamente quello che stai cercando.

+0

Grazie per la risposta. Ho già personalizzato Chrome sulla finestra, e ho catturato i messaggi di Windows dal menu di sistema sul pulsante Riduci a icona: nella barra del titolo, menu di sistema sulla barra delle applicazioni, menu di sistema su Alt + Spazio. Ma non riesco ancora a catturare l'evento nell'applicazione per Toggle Desktop (Win + D) e Minimize All (Win + M) ... –