WPF window state when restored from maximized gets stuck in odd state -


i'm seeing strange behaviour wpf. have form 3 buttons on it. 1 button should make window fullscreen, 1 should center on monitor on, third button should restore window normal position.

the xaml is

<window x:class="testrestore.mainwindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:local="clr-namespace:testrestore"         mc:ignorable="d"         title="mainwindow" height="350" width="525" resizemode="canresizewithgrip" windowstartuplocation="centerscreen">     <grid>         <button content="max" horizontalalignment="left" margin="10,10,0,0" verticalalignment="top" width="94" click="max_click" name="max_button"/>         <button content="center" horizontalalignment="left" margin="10,35,0,0" verticalalignment="top" width="94" click="center_click" name="center_button"/>         <button content="restore" horizontalalignment="left" margin="227,143,0,0" verticalalignment="top" width="75" click="restore_click" name="restore_button" isenabled="false"/>     </grid> </window> 

and code below. strange behaviour when maximize, , restore window, position correctly restored window still thinks it's maximized (the maximize button looks restore button , can't resize window though resizemode has been set canresizewithgrip).

when maximized window has been restored, , thinks still maximized though window position isn't maximized, moving window manually dragging title bar enough cause correct non-maximized mode.

also, if maximize restore window , maximize again without moving it, maximized window position incorrect (not in top left).

and mystery deepens. if maximize restore window, press alt, press down (to window menu) , select 'move' , move window around keyboard, stays stuck in 'bogus not-mazimized mode' though window being moved, seems way unstick move mouse.

using system; using system.runtime.interopservices; using system.windows; using system.windows.interop;  namespace testrestore {     public partial class mainwindow : window     {         windowstyle old_window_style;         windowstate old_window_state;         double old_left;         double old_top;         double old_width;         double old_height;          public mainwindow()         {             initializecomponent();         }          // remember position, style , state         private void savewindowpos()         {             old_window_style = windowstyle;             old_window_state = windowstate;             old_left = left;             old_top = top;             old_width = width;             old_height = height;             max_button.isenabled = false;             center_button.isenabled = false;             restore_button.isenabled = true;         }          // put position, style , state         private void restorewindowpos()         {             windowstyle = old_window_style;             windowstate = old_window_state;             resizemode = resizemode.canresizewithgrip;             left = old_left;             top = old_top;             width = old_width;             height = old_height;             max_button.isenabled = true;             center_button.isenabled = true;             restore_button.isenabled = false;         }          // make centered or fullscreen         private void setactivepos(bool full_screen)         {             savewindowpos();             hide();             if (full_screen)             {                 resizemode = resizemode.noresize;                 windowstyle = windowstyle.none;                 windowstate = windowstate.maximized;             }             else             {                 size s = new size(800, 600);                 point p = centerrectinmonitor(this, s);                 left = p.x;                 top = p.y;                 width = s.width;                 height = s.height;                 resizemode = resizemode.noresize;                 windowstate = windowstate.normal;             }             show();         }          private void restore_click(object sender, routedeventargs e)         {             hide();             restorewindowpos();             show();         }          private void max_click(object sender, routedeventargs e)         {             setactivepos(true);         }          private void center_click(object sender, routedeventargs e)         {             setactivepos(false);         }          // interop          public const int32 monitor_defaulttoprimary = 0x00000001;         public const int32 monitor_defaulttonearest = 0x00000002;          [dllimport("user32.dll")]         public static extern intptr monitorfromwindow(intptr handle, int32 flags);          [dllimport("user32.dll", charset = charset.auto)]         public static extern bool getmonitorinfo(intptr hmonitor, ref monitorinfoex lpmi);          // size of device name string         private const int cchdevicename = 32;          [structlayout(layoutkind.sequential, charset = charset.auto)]         public struct monitorinfoex         {             public int size;             public rectstruct monitor;             public rectstruct workarea;             public uint flags;              [marshalas(unmanagedtype.byvaltstr, sizeconst = cchdevicename)]             public string devicename;              public void init()             {                 this.size = 40 + 2 * cchdevicename;                 this.devicename = string.empty;             }         }          [structlayout(layoutkind.sequential)]         public struct rectstruct         {             public int left;             public int top;             public int right;             public int bottom;              public int width             {                                 {                     return right - left;                 }             }              public int height             {                                 {                     return bottom - top;                 }             }         }          public static monitorinfoex getmonitorfromwindow(window w)         {             var hwnd = new windowinterophelper(w).ensurehandle();             var monitor = monitorfromwindow(hwnd, monitor_defaulttonearest);             monitorinfoex monitor_info = new monitorinfoex();             monitor_info.init();             getmonitorinfo(monitor, ref monitor_info);             return monitor_info;         }          // work out how rect of 'size size' should centered on monitor containing 'window w'         public static point centerrectinmonitor(window w, size size)         {             var source = presentationsource.fromvisual(w);             double x_scale = source.compositiontarget.transformtodevice.m11;             double y_scale = source.compositiontarget.transformtodevice.m22;             var width = size.width * x_scale;             var height = size.height * y_scale;             var monitor_info = getmonitorfromwindow(w);             size s = new size(monitor_info.monitor.width, monitor_info.monitor.height);             point p = new point(monitor_info.monitor.left, monitor_info.monitor.top);             point c = new point(p.x + s.width / 2, p.y + s.height / 2);             return new point((c.x - width / 2) / x_scale, (c.y - height / 2) / y_scale);         }     } } 

i don't have complete answer you. find code starts working lot better once remove hide() , show() calls.

    private void restore_click(object sender, routedeventargs e)     { //            hide();         restorewindowpos(); //            show();     } 

i'm sure put in reduce flicker, think happening hide() , show() calls flipping ws_visible bit in window style word of underlying os window same word contains ws_maximize , ws_border , other things manipulating. see https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx

it take more research figure out going on, fundamental problem believe "leaky abstraction". code sets top, left, style , state if these independent uncoupled variables. not! set left, os setwindowpos() function must called requires not upper left coordinate, window size, z order visibility flags , whether windows maximized! see https://msdn.microsoft.com/en-us/library/windows/desktop/ms633545(v=vs.85).aspx. each time set 1 of these "independent" variables pounding setwindowpos(). api call harks bad old days when cpu cycles precious , need pack functionality possible each api call.

ironically making code inefficient. think thing straighten out bypass leaking abstraction of system.windows.window , call setwindowpos , possibility other api functions directly user32.dll. things lot more predicable.


Comments

Popular posts from this blog

node.js - Node js - Trying to send POST request, but it is not loading javascript content -

javascript - Replicate keyboard event with html button -

javascript - Web audio api 5.1 surround example not working in firefox -