2

I'm getting some very odd behaviour with a WPF window that I am able to recreate with a basic application. When I minimize my window from a maximized state, then restore my window it does not return maximized. I've implemented code to try and counter this, but the window still returns to a WindowState.Normal.

An important thing to note about this is the this only happen when I am running the application stand-alone. If I run in debug mode in visual studio everything works as expected. Also, this behaviour occurs on multiple boxes, not just my own.

Steps to reproduce with code below:

  1. double-click WpfApplication1.exe
  2. ensure application is maximized
  3. click the minimize button in the top right
  4. click the application in the taskbar

    Expected Result: application window returns to a maximized state

    Actual Result: application window is in restored state, with WindowState = WindowState.Normal

Here is the XAML code for the demo window.

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    WindowState="Maximized"
    Activated="MainWindow_OnActivated"
    StateChanged="MainWindow_OnStateChanged">
    <Grid>

    </Grid>
</Window>

and the code-behind:

public partial class MainWindow : Window
{
  private WindowState _lastWindowState;
  private bool _activating;

  public MainWindow()
  {
    InitializeComponent();

    _lastWindowState = WindowState.Normal;
  }

  private void MainWindow_OnActivated(object sender, EventArgs e)
  {

    if (WindowState == WindowState.Minimized)
    {
      WindowState = _lastWindowState;
    }

  }

  private void MainWindow_OnStateChanged(object sender, EventArgs e)
  {
    if (WindowState != WindowState.Minimized)
    {
      _lastWindowState = WindowState;
    }
  }
}

In my real application I placed logging code before and after the WindowState set in the OnActivated function and in the StateChanged function. When activating from minimized I get the following:

OnActivated 1  - _lastWindowState: Maximized
OnStateChanged - _lastWindowState: Maximized
OnActivated 2  - _lastWindowState: Maximized
OnStateChanged - _lastWindowState: Normal

Finally, in case this helps, this is the Environment.StackTrace in the last StateChanged call that happens:

at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at MapViewer.MainWindow.MainWindow_OnStateChanged(Object sender, EventArgs e) in c:\APP\MainWindow.xaml.cs:line 994
   at System.Windows.Window.OnStateChanged(EventArgs e)
   at System.Windows.Window.WmSizeChanged(IntPtr wParam)
   at System.Windows.Window.WindowFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.PublicHooksFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at MapViewer.App.Main() in c:\Projects\APP\obj\x86\Debug\App.g.cs:line 0
flamebaud
  • 978
  • 1
  • 9
  • 26
  • 1
    Do you have a reason for including this code? It seems that what you're trying to accomplish is the default Maximization/Minimization behavior in WPF, as long as you have ResizeMode=CanResize – Daniel Simpkins May 01 '14 at 19:57
  • The real functionality that happens is that I have another app that sends a message to this app to activate. When the app activates itself in a minimized state it does not restore the window. I've tried the solution from http://stackoverflow.com/questions/5531548/how-to-restore-a-minimized-window-in-code-behind but it gives the same functionality. `ResizeMode = CanResize` does not help – flamebaud May 02 '14 at 12:18
  • Have you tried the second solution from that question(Accessing the OS APIs directly)? http://stackoverflow.com/a/5535341/2116047 – Daniel Simpkins May 02 '14 at 13:24
  • I have, on its own with SW_RESTORE as well as using my `_lastWindowState` process with SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED. Neither seem to be effective. – flamebaud May 02 '14 at 17:59
  • "..I have another app that sends a message to this app to activate..": Microsoft intentionally disables some old Win32 API window functions, mainly for security reasons, to prevent other apps from hacking other app's windows etc. and WPF processing pipeline is also different. Prefered way is to use a newer cleaner API (e.g. WCF) for inter application communication and leave the window management completely up to your application. The other app sends you ACTIVATE signal and you call WPF Window... anything you need to do – xmojmr May 22 '14 at 06:51
  • That's interesting to know, thanks xmojmr. Unfortunately this doesn't really address the issue, since the example I've given above is an independent app that doesn't have any inter-application communication and still has the problem. – flamebaud May 23 '14 at 12:06

0 Answers0