2009-05-29 17 views
10

Necesito manejar la aplicación WPF justo antes de que se minimice, no cuando ya está allí. Encontré en el objeto Window StateChanged, pero se dispara cuando el objeto Window ya está en estado Minimizar, entonces es demasiado tarde.Evento Window State Changing en WPF

Por lo tanto, necesito algo así como el evento "StateChanging" para manejar, mientras que el objeto Window todavía está en estado anterior.

¿Es posible crear dicho evento?

Respuesta

11

Se encontraron mensajes de Windows en la ventana de llamada justo antes de minimizar el uso de Spy ++. El primero que se llama es WM_WINDOWPOSCHANGING. No sabía que Windows está moviendo la ventana en -32000, -32000 punto de ubicación al minimizar viuda, y esos fueron los parámetros en WM_WINDOWPOSCHANGING. Sin embargo, he probado solo en Vista. código http://blogs.msdn.com/oldnewthing/archive/2004/10/28/249044.aspx

utilizado aquí fue publicada por Nir here

aquí es código de ejemplo

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

No creo que puedas hacerlo directamente.

Minimizar la llamada a la ventana puede producirse en varios lugares, no solo en el botón minimizar en la ventana de Chrome (por ejemplo, haciendo clic derecho en la barra de tareas o en el Administrador de tareas de Windows) y AFAIK, no hay forma de controle directamente los eventos de botón disparados desde Window Chrome (si alguien sabe cómo hacerlo, hágamelo saber).

La buenas noticias es que puede fingir, pero no es trivial, por lo que tendrá que decidir si vale la pena. Primero, deberá reemplazar el Window Chrome estándar por el suyo. Puede averiguar cómo hacerlo here.

En segundo lugar, deberá crear sus propios botones "Maximizar/Minimizar/Cerrar" y conectar los eventos a los comportamientos apropiados. Dado que esta es su propia interfaz de usuario, puede escuchar y cancelar los eventos de botón como lo desee.

Tenga en cuenta que aún no podrá detectar o evitar que los usuarios minimicen a través del administrador de tareas TaskBar/Windows, por lo que puede no ser exactamente lo que está buscando.

+0

Gracias por responder. Ya tengo Chrome personalizado en la ventana, y he capturado mensajes de Windows desde el menú del sistema en el botón minimizar: en la barra de título, menú del sistema en la barra de tareas, menú del sistema en Alt + Espacio. Pero aún no puedo capturar el evento en la aplicación para Toggle Desktop (Win + D) y Minimize All (Win + M) ... –