//------------------------------------------------------ // // Interface ITransformProvider // //------------------------------------------------------ #region Interface ITransformProvider void ITransformProvider.Move( double x, double y ) { if ( ! ((ITransformProvider)this).CanMove ) throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); int extendedStyle = GetWindowExStyle(); if ( IsBitSet(extendedStyle, SafeNativeMethods.WS_EX_MDICHILD) ) { // we always deal in screen pixels. But if its an MDI window it interprets these as // client pixels so convert them to get the expected results. NativeMethods.POINT point = new NativeMethods.POINT((int)x, (int)y); NativeMethods.HWND hwndParent = SafeNativeMethods.GetAncestor(NativeMethods.HWND.Cast(_hwnd), SafeNativeMethods.GA_PARENT); if (!MapWindowPoints(NativeMethods.HWND.NULL, hwndParent, ref point, 1)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } x = point.x; y = point.y; // Make sure the MDI child stays on the parents client area. NativeMethods.RECT currentRect = new NativeMethods.RECT(); if (!Misc.GetWindowRect(_hwnd, out currentRect)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } int currentHeight = currentRect.bottom - currentRect.top; int currentWidth = currentRect.right - currentRect.left; int dx = SafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CXHSCROLL); int dy = SafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CYHSCROLL); // If to far to the left move right edge to be visible. // Move the left edge the absalute differance of the right to the origin plus a little more to be visible. if (x + currentWidth < 0) { x += ((x + currentWidth) * -1 + dx); } // If to far off the top move bottom edge down to be visible. // Move the top edge the absalute differance of the bottom to the origin plus a little more to be visible. if (y + currentHeight < 0) { y += ((y + currentHeight) * -1 + dy); } NativeMethods.RECT parentRect = new NativeMethods.RECT(); if (!Misc.GetClientRect(hwndParent, out parentRect)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } // If to far to the right move left edge to be visible. // Move the left edge back the diffance of it and the parent's client area right side plus a little more to be visible. if (x > parentRect.right) { x -= (x - parentRect.right + dx); } // If to far off the bottome move top edge down to be visible. // Move the top edge up the diffance of it and the parent's client area bottom side plus a little more to be visible. if (y > parentRect.bottom) { y -= (y - parentRect.bottom + dy); } } // position the window keeping the zorder the same and not resizing. // We do this first so that the window is moved in terms of screen coordinates. // The WindowPlacement APIs take in to account the workarea which ends up // putting the window in the wrong place if (!Misc.SetWindowPos(_hwnd, NativeMethods.HWND.NULL, (int)x, (int)y, 0, 0, UnsafeNativeMethods.SWP_NOSIZE | UnsafeNativeMethods.SWP_NOZORDER | UnsafeNativeMethods.SWP_NOACTIVATE)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } UnsafeNativeMethods.WINDOWPLACEMENT wp = new UnsafeNativeMethods.WINDOWPLACEMENT(); wp.length = Marshal.SizeOf(typeof(UnsafeNativeMethods.WINDOWPLACEMENT)); // get the WINDOWPLACEMENT information. This includes the coordinates in // terms of the workarea. if (!Misc.GetWindowPlacement(_hwnd, ref wp)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } int style = GetWindowStyle(); if (style == 0) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } if ( IsBitSet(style, SafeNativeMethods.WS_MINIMIZE) ) { // If the window is minimized the parameters have to be setup differently wp.ptMinPosition.y = (int) y; wp.ptMinPosition.x = (int) x; wp.flags = UnsafeNativeMethods.WPF_SETMINPOSITION; // Use SetWindowPlacement to move the window because it handles the case where the // window is move completly off the screen even in the multi-mon case. If this happens // it will place the window on the primary monitor at a location closest to the taget. if (!Misc.SetWindowPlacement(_hwnd, ref wp)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } } else { NativeMethods.RECT currentRect = new NativeMethods.RECT(); if (!Misc.GetWindowRect(_hwnd, out currentRect)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } // Use SetWindowPlacement to move the window because it handles the case where the // window is move completly off the screen even in the multi-mon case. If this happens // it will place the window on the primary monitor at a location closest to the taget. if (!Misc.SetWindowPlacement(_hwnd, ref wp)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } // check to make sure SetWindowPlacement has not changed the size of our window // There may be a bug in SetWindowPlacement. int currentHeight = currentRect.bottom - currentRect.top; int currentWidth = currentRect.right - currentRect.left; if (!Misc.GetWindowPlacement(_hwnd, ref wp)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } int newHeight = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; int newWidth = wp.rcNormalPosition.right -wp.rcNormalPosition.left; if ( currentHeight != newHeight || currentWidth != newWidth ) { wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + currentHeight; wp.rcNormalPosition.right = wp.rcNormalPosition.left + currentWidth; if (!Misc.SetWindowPlacement(_hwnd, ref wp)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } } } }
void ITransformProvider.Resize( double width, double height ) { if ( !SafeNativeMethods.IsWindow( _hwnd ) ) throw new ElementNotAvailableException(); int widthInt = (int) width; int heightInt = (int) height; if ( ! ((ITransformProvider)this).CanResize ) throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); UnsafeNativeMethods.MINMAXINFO minMaxInfo = new UnsafeNativeMethods.MINMAXINFO(); // get the largest window size that can be produced by using the borders to size the window int x = SafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CXMAXTRACK); int y = SafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CYMAXTRACK); minMaxInfo.ptMaxSize = new NativeMethods.POINT( x, y ); minMaxInfo.ptMaxPosition = new NativeMethods.POINT(0, 0); minMaxInfo.ptMinTrackSize = new NativeMethods.POINT(1, 1); minMaxInfo.ptMaxTrackSize = new NativeMethods.POINT( x, y ); // if the window stopped responding there is a chance that resizing will not work // Don't check the return from SendMessageTimeout and go ahead // and try to resize in case it works. The minMaxInfo struct has resonable // values even if this fails. Misc.SendMessageTimeout(_hwnd, UnsafeNativeMethods.WM_GETMINMAXINFO, IntPtr.Zero, ref minMaxInfo); if ( widthInt < minMaxInfo.ptMinTrackSize.x ) widthInt = minMaxInfo.ptMinTrackSize.x; if ( heightInt < minMaxInfo.ptMinTrackSize.y ) heightInt = minMaxInfo.ptMinTrackSize.y; if ( widthInt > minMaxInfo.ptMaxTrackSize.x ) widthInt = minMaxInfo.ptMaxTrackSize.x; if ( heightInt > minMaxInfo.ptMaxTrackSize.y ) heightInt = minMaxInfo.ptMaxTrackSize.y; UnsafeNativeMethods.WINDOWPLACEMENT wp = new UnsafeNativeMethods.WINDOWPLACEMENT(); wp.length = Marshal.SizeOf(typeof(UnsafeNativeMethods.WINDOWPLACEMENT)); // get the WINDOWPLACEMENT information if (!Misc.GetWindowPlacement(_hwnd, ref wp)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } // Calculate the new right and bottom for how the user wants the window resized and update the struct wp.rcNormalPosition.right = (widthInt + wp.rcNormalPosition.left); wp.rcNormalPosition.bottom = (heightInt + wp.rcNormalPosition.top); // Use SetWindowPlacement to move the window because it handles the case where the // window is sized completly off the screen even in the multi-mon case. If this happens // it will place the window on the primary monitor at a location closes to the taget. if (!Misc.SetWindowPlacement(_hwnd, ref wp)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } }
//------------------------------------------------------ // // Interface IWindowProvider // //------------------------------------------------------ #region Interface IWindowProvider void IWindowProvider.SetVisualState( WindowVisualState state ) { if ( !SafeNativeMethods.IsWindow( _hwnd ) ) throw new ElementNotAvailableException(); switch ( state ) { case WindowVisualState.Normal: { // you can't really do anything to a disabled window if ( IsBitSet(GetWindowStyle(), SafeNativeMethods.WS_DISABLED) ) throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); // If already in the normal state, do not need to do anything. if (((IWindowProvider)this).VisualState == WindowVisualState.Normal) { return; } ClearMenuMode(); UnsafeNativeMethods.WINDOWPLACEMENT wp = new UnsafeNativeMethods.WINDOWPLACEMENT(); wp.length = Marshal.SizeOf(typeof(UnsafeNativeMethods.WINDOWPLACEMENT)); // get the WINDOWPLACEMENT information if (!Misc.GetWindowPlacement(_hwnd, ref wp)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } wp.showCmd = UnsafeNativeMethods.SW_RESTORE; // Use SetWindowPlacement to set state to normal because if the window is maximized then minimized // sending SC_RESTORE puts it back to maximized instead of normal. if (!Misc.SetWindowPlacement(_hwnd, ref wp)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } return; } case WindowVisualState.Minimized: { if (!((IWindowProvider)this).Minimizable) throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); // If already minimzed, do not need to do anything. if (((IWindowProvider)this).VisualState == WindowVisualState.Minimized) { return; } ClearMenuMode(); if (!Misc.PostMessage(_hwnd, UnsafeNativeMethods.WM_SYSCOMMAND, (IntPtr)UnsafeNativeMethods.SC_MINIMIZE, IntPtr.Zero)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } return; } case WindowVisualState.Maximized: { if ( ! ((IWindowProvider)this).Maximizable ) throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); // If already maximized, do not need to do anything. if (((IWindowProvider)this).VisualState == WindowVisualState.Maximized) { return; } ClearMenuMode(); if (!Misc.PostMessage(_hwnd, UnsafeNativeMethods.WM_SYSCOMMAND, (IntPtr)UnsafeNativeMethods.SC_MAXIMIZE, IntPtr.Zero)) { throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); } return; } default: { Debug.Assert(false,"unexpected switch() case:"); throw new ArgumentException(SR.Get(SRID.UnexpectedWindowState),"state"); } } }