代码之家  ›  专栏  ›  技术社区  ›  Andrija

WPF中的窗口状态更改事件

  •  10
  • Andrija  · 技术社区  · 17 年前

    我需要在WPF应用程序最小化之前处理它,而不是当它已经存在时。 我发现window对象的状态发生了变化,但当window对象已经处于最小化状态时,它就会触发,那就太晚了。

    所以,当窗口对象仍处于前一状态时,我需要处理类似“StateChanging”事件的事件。

    是否可以创建此类事件?

    2 回复  |  直到 17 年前
        1
  •  11
  •   Community Mohan Dere    9 年前

    在使用Spy++最小化之前在窗口上找到调用的Windows消息。第一个被称为wm_WindowPosChanging。 我不知道Windows在-32000、-32000位置点移动窗口,当最小化寡妇时,这些是wm_WindowPosChanging中的参数。不过,我只在Vista上测试过。 http://blogs.msdn.com/oldnewthing/archive/2004/10/28/249044.aspx

    这里使用的代码是由NIR发布的 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;           
        }       
    
    }
    }
    
        2
  •  0
  •   micahtan    17 年前

    我认为你不能直接这么做。

    对窗口的最小化调用可以在多个位置发生,而不仅仅是窗口chrome上的最小化按钮(例如,右键单击任务栏或从Windows任务管理器),而且,对于afaik,无法直接处理从窗口chrome触发的按钮事件(如果有人知道如何执行此操作,请通知我!).

    这个 好消息 是说你可以伪造它,但它并不琐碎,所以你必须决定它是否值得。首先,您必须用自己的浏览器替换标准的窗口浏览器。你可以知道怎么做 here .

    其次,您必须创建自己的“最大化/最小化/关闭”按钮,并将事件连接到适当的行为。因为这是您自己的用户界面,所以您可以随意收听和取消按钮事件。

    请记住,您仍然无法通过任务栏/Windows任务管理器检测或阻止用户最小化,因此它可能不是您要查找的内容。