2009-05-29 12 views
10

Ich muss mit WPF-Anwendung umgehen, bevor es geht Minimize, nicht wenn es schon da ist. Ich fand auf Window-Objekt StateChanged, aber es wird ausgelöst, wenn Window-Objekt bereits im Zustand Minimieren ist, dann ist es zu spät.Window StateChanging-Ereignis in WPF

So brauche ich etwas wie "StateChanging" -Ereignis zu behandeln, während Window-Objekt noch im vorherigen Zustand ist.

Ist es möglich, ein solches Ereignis zu erstellen?

Antwort

11

Gefundene Windows-Nachrichten Fenster direkt vor dem Minimieren mit Spy ++ aufgerufen. Der erste Aufruf lautet WM_WINDOWPOSCHANGING. Ich wusste nicht, Fenster bewegt Fenster auf -32000, -32000 Ortspunkt, wenn Witwe zu minimieren, und das waren die Parameter in WM_WINDOWPOSCHANGING. Allerdings habe ich nur auf Vista getestet. http://blogs.msdn.com/oldnewthing/archive/2004/10/28/249044.aspx

Code hier verwendet wurde von Nir geschrieben here

hier ist Beispielcode

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

Ich glaube nicht, dass Sie es direkt tun können.

Ein Anruf zum Fenster minimieren kann von einer Reihe von Orten passieren, nicht nur die Minimieren-Taste auf dem Fenster Chrome (z. B. mit der rechten Maustaste auf die Taskleiste oder von Windows Task-Manager), und AFAIK, es gibt keine Möglichkeit gehen Sie direkt mit Schaltflächenereignissen um, die aus dem Fenster "Chrome" ausgelöst wurden (wenn jemand das weiß, lassen Sie es mich wissen!).

Die gute Nachrichten ist, dass Sie es vortäuschen können, aber es ist nicht trivial, also müssen Sie entscheiden, ob es das wert ist. Zuerst müssen Sie das Standardfenster Chrome durch Ihr eigenes ersetzen. Sie können herausfinden, wie man das macht here.

Zweitens müssen Sie Ihre eigenen Schaltflächen "Maximieren/Minimieren/Schließen" erstellen und die Ereignisse an die entsprechenden Verhaltensweisen anschließen. Da dies Ihre eigene Benutzeroberfläche ist, können Sie die Button-Ereignisse nach Belieben anhören und abbrechen.

Denken Sie daran, dass Sie die Minimierung von Benutzern über den TaskBar/Windows Task-Manager immer noch nicht erkennen oder verhindern können. Daher ist es möglicherweise nicht genau das, wonach Sie suchen.

+0

Vielen Dank für Ihre Antwort. Ich habe bereits benutzerdefinierte Chrome auf Fenster, und ich habe Windows-Meldungen aus dem Systemmenü auf Schaltfläche minimieren: in der Titelleiste, Systemmenü auf der Taskleiste, Systemmenü auf Alt + Space. Aber ich kann immer noch kein Ereignis in der Anwendung für Toggle Desktop (Win + D) und Minimize All (Win + M) erfassen ... –