我需要在最小化之前處理WPF應用程序,而不是已經存在的時候。 我在窗口對象StateChanged上找到了它,但是當Window對象已經處於最小化狀態時它會觸發,那就太遲了。WPF中的Window StateChanging事件
所以,我需要像「StateChanging」事件來處理,而Window對象仍處於以前的狀態。
是否可以創建此類事件?
我需要在最小化之前處理WPF應用程序,而不是已經存在的時候。 我在窗口對象StateChanged上找到了它,但是當Window對象已經處於最小化狀態時它會觸發,那就太遲了。WPF中的Window StateChanging事件
所以,我需要像「StateChanging」事件來處理,而Window對象仍處於以前的狀態。
是否可以創建此類事件?
在最小化使用Spy ++之前發現在窗口上調用的窗口消息。第一個被調用的是WM_WINDOWPOSCHANGING。 當我最小化widow時,我不知道窗口正在移動-32000,-32000位置點,這些是WM_WINDOWPOSCHANGING中的參數。雖然,我測試過的只是Vista。這裏使用http://blogs.msdn.com/oldnewthing/archive/2004/10/28/249044.aspx
代碼被張貼尼爾here
這裏是示例代碼
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;
}
}
}
我不認爲你能夠直接做到這一點。
A最小化對窗口的調用可能發生在很多地方,而不僅僅是Window Chrome上的最小化按鈕(例如,右鍵單擊任務欄或從Windows任務管理器)和AFAIK,沒有辦法直接處理Window Chrome觸發的按鈕事件(如果有人知道如何做到這一點,請告訴我!)。
好消息是你可以僞裝它,但它不是微不足道的,所以你必須決定它是否值得。首先,你必須用你自己的代替標準的Window Chrome。你可以找到如何做到這一點here。其次,您必須創建您自己的「最大化/最小化/關閉」按鈕,並將事件連接到適當的行爲。由於這是您自己的用戶界面,因此您可以隨意傾聽並取消按鈕事件。
請記住,您仍然無法通過TaskBar/Windows任務管理器檢測或阻止用戶最小化,因此它可能不是您正在查找的內容。
謝謝你的回覆。我已經在窗口上自定義了一個chrome,並且我從按鈕上的系統菜單中捕獲窗口消息最小化:在標題欄,任務欄上的系統菜單,Alt + Space上的系統菜單中。但我仍然無法捕獲應用程序中的切換桌面(Win + D)和最小化全部(Win + M)事件... – 2009-05-30 00:29:37