public override void Execute(SnapAction action, IJobContext context) { var workingArea = context.Display.WorkingArea; var bounds = context.Window.Bounds; switch (action.ResizeType) { case ResizeType.Vertical: bounds = new Rectangle( bounds.Left, workingArea.Top, bounds.Width, workingArea.Height); break; case ResizeType.Horizontal: bounds = new Rectangle( workingArea.Left, bounds.Top, workingArea.Width, bounds.Height); break; default: return; } bounds += context.Window.Border; User32Api.SetWindowPos(context.Window.Handle, IntPtr.Zero, bounds.X, bounds.Y, bounds.Width, bounds.Height, WindowPos.SWP_SHOWWINDOW); }
public void SetTopMost(bool isTopMost) { var topMostHandle = isTopMost ? HWnd.TopMost : HWnd.NoTopMost; User32Api.SetWindowPos(WindowHandle, topMostHandle, 0, 0, 0, 0, SetWindowPosFlags.IgnoreMove | SetWindowPosFlags.IgnoreResize); }
public override void Execute(PlacementAction action, IJobContext context) { var display = context.Display; if (action.Placement.DisplayIndex is int displayIndex) { if (_displayService.Displays.ContainsKey(displayIndex)) { display = _displayService.Displays[displayIndex]; } else { return; } } if (action.Placement.Bounds == null) { var bounds = display.WorkingArea; User32Api.SetWindowPos(context.Window.Handle, IntPtr.Zero, bounds.X, bounds.Y, bounds.Width, bounds.Height, WindowPos.SWP_SHOWWINDOW); User32Api.ShowWindow(context.Window.Handle, ShowWindowCommands.ShowMaximized); } else { var bounds = display.WorkingArea.CropByPercentage(action.Placement.Bounds) + context.Window.Border; User32Api.SetWindowPos(context.Window.Handle, IntPtr.Zero, bounds.X, bounds.Y, bounds.Width, bounds.Height, WindowPos.SWP_SHOWWINDOW); } }
/// <summary> /// Show the thumbnail of the supplied window above (or under) the parent Control /// </summary> /// <param name="window">WindowDetails</param> /// <param name="parentControl">Control</param> public void ShowThumbnail(IInteropWindow window, Control parentControl) { UnregisterThumbnail(); Dwm.DwmRegisterThumbnail(Handle, window.Handle, out _thumbnailHandle); if (_thumbnailHandle == IntPtr.Zero) { return; } Dwm.DwmQueryThumbnailSourceSize(_thumbnailHandle, out var sourceSize); var thumbnailHeight = 200; var thumbnailWidth = (int)(thumbnailHeight * (sourceSize.Width / (float)sourceSize.Height)); if (parentControl != null && thumbnailWidth > parentControl.Width) { thumbnailWidth = parentControl.Width; thumbnailHeight = (int)(thumbnailWidth * (sourceSize.Height / (float)sourceSize.Width)); } Width = thumbnailWidth; Height = thumbnailHeight; // Prepare the displaying of the Thumbnail var props = new DwmThumbnailProperties { Opacity = 255, Visible = true, SourceClientAreaOnly = false, Destination = new NativeRect(0, 0, thumbnailWidth, thumbnailHeight) }; Dwm.DwmUpdateThumbnailProperties(_thumbnailHandle, ref props); if (parentControl != null) { AlignToControl(parentControl); } if (!Visible) { Show(); } // Make sure it's on "top"! if (parentControl != null) { User32Api.SetWindowPos(Handle, parentControl.Handle, 0, 0, 0, 0, WindowPos.SWP_NOMOVE | WindowPos.SWP_NOSIZE | WindowPos.SWP_NOACTIVATE); } }
/// <summary> /// Move the specified window to a new location /// </summary> /// <param name="interopWindow">IInteropWindow</param> /// <param name="location">NativePoint with the offset</param> /// <returns>IInteropWindow for fluent calls</returns> public static IInteropWindow MoveTo(this IInteropWindow interopWindow, NativePoint location) { User32Api.SetWindowPos(interopWindow.Handle, IntPtr.Zero, location.X, location.Y, 0, 0, WindowPos.SWP_NOSIZE | WindowPos.SWP_SHOWWINDOW | WindowPos.SWP_NOACTIVATE | WindowPos.SWP_NOZORDER); interopWindow.Info = null; return(interopWindow); }
/// <summary> /// Message handler of the Per_Monitor_DPI_Aware window. /// The handles the WM_DPICHANGED message and adjusts window size, graphics and text based on the DPI of the monitor. /// The window message provides the new window size (lparam) and new DPI (wparam) /// See /// <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn312083(v=vs.85).aspx">WM_DPICHANGED message</a> /// </summary> /// <param name="windowMessageInfo">WindowMessageInfo</param> /// <returns>IntPtr</returns> internal bool HandleWindowMessages(WindowMessageInfo windowMessageInfo) { bool handled = false; var currentDpi = DefaultScreenDpi; bool isDpiMessage = false; switch (windowMessageInfo.Message) { // Handle the WM_NCCREATE for Forms / controls, for WPF this is done differently case WindowsMessages.WM_NCCREATE: if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Processing {0} event, enabling DPI scaling for window {1}", windowMessageInfo.Message, windowMessageInfo.Handle); } TryEnableNonClientDpiScaling(windowMessageInfo.Handle); break; // Handle the WM_CREATE, this is where we can get the DPI via system calls case WindowsMessages.WM_CREATE: isDpiMessage = true; if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Processing {0} event, retrieving DPI for window {1}", windowMessageInfo.Message, windowMessageInfo.Handle); } currentDpi = NativeDpiMethods.GetDpi(windowMessageInfo.Handle); _scopedThreadDpiAwarenessContext.Dispose(); break; // Handle the DPI change message, this is where it's supplied case WindowsMessages.WM_DPICHANGED: isDpiMessage = true; if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Processing {0} event, resizing / positioning window {1}", windowMessageInfo.Message, windowMessageInfo.Handle); } // Retrieve the adviced location var lprNewRect = (NativeRect)Marshal.PtrToStructure(windowMessageInfo.LongParam, typeof(NativeRect)); // Move the window to it's location, and resize User32Api.SetWindowPos(windowMessageInfo.Handle, IntPtr.Zero, lprNewRect.Left, lprNewRect.Top, lprNewRect.Width, lprNewRect.Height, WindowPos.SWP_NOZORDER | WindowPos.SWP_NOOWNERZORDER | WindowPos.SWP_NOACTIVATE); currentDpi = (uint)windowMessageInfo.WordParam & 0xFFFF; // specify that the message was handled handled = true; break; case WindowsMessages.WM_PAINT: // This is a workaround for non DPI aware applications, these don't seem to get a WM_CREATE if (Dpi == 0) { isDpiMessage = true; currentDpi = NativeDpiMethods.GetDpi(windowMessageInfo.Handle); } break; case WindowsMessages.WM_SETICON: // This is a workaround for handling WinProc outside of the class if (_needsListenerWorkaround) { isDpiMessage = true; // disable workaround _needsListenerWorkaround = false; currentDpi = NativeDpiMethods.GetDpi(windowMessageInfo.Handle); } break; case WindowsMessages.WM_DPICHANGED_BEFOREPARENT: if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Dpi changed on {0} before parent", windowMessageInfo.Handle); } break; case WindowsMessages.WM_DPICHANGED_AFTERPARENT: if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Dpi changed on {0} after parent", windowMessageInfo.Handle); } break; case WindowsMessages.WM_DESTROY: if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Completing the observable for {0}", windowMessageInfo.Handle); } // If the window is destroyed, we complete the subject _onDpiChanged.OnCompleted(); // Dispose all resources Dispose(); break; } // Check if the DPI was changed, if so call the action (if any) if (!isDpiMessage) { return(false); } if (Dpi != currentDpi) { var beforeDpi = Dpi; if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Changing DPI from {0} to {1}", beforeDpi, currentDpi); } Dpi = currentDpi; _onDpiChanged.OnNext(new DpiChangeInfo(beforeDpi, currentDpi)); } else if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("DPI was unchanged from {0}", Dpi); } return(handled); }
/// <summary> /// Message handler of the Per_Monitor_DPI_Aware window. /// The handles the WM_DPICHANGED message and adjusts window size, graphics and text based on the DPI of the monitor. /// The window message provides the new window size (lparam) and new DPI (wparam) /// See /// <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn312083(v=vs.85).aspx">WM_DPICHANGED message</a> /// </summary> /// <param name="hwnd">IntPtr with the hWnd</param> /// <param name="msg">The Windows message</param> /// <param name="wParam">IntPtr</param> /// <param name="lParam">IntPtr</param> /// <param name="handled">ref bool</param> /// <returns>IntPtr</returns> internal IntPtr HandleWindowMessages(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { var windowsMessage = (WindowsMessages)msg; var currentDpi = (int)DefaultScreenDpi; bool isDpiMessage = false; switch (windowsMessage) { // Handle the WM_NCCREATE for Forms / controls, for WPF this is done differently case WindowsMessages.WM_NCCREATE: TryEnableNonClientDpiScaling(hwnd); break; // Handle the WM_CREATE, this is where we can get the DPI via system calls case WindowsMessages.WM_CREATE: isDpiMessage = true; Log.Verbose().WriteLine("Processing {0} event, retrieving DPI for window {1}", windowsMessage, hwnd); currentDpi = GetDpi(hwnd); break; // Handle the DPI change message, this is where it's supplied case WindowsMessages.WM_DPICHANGED: isDpiMessage = true; Log.Verbose().WriteLine("Processing {0} event, resizing / positioning window {1}", windowsMessage, hwnd); // Retrieve the adviced location var lprNewRect = (NativeRect)Marshal.PtrToStructure(lParam, typeof(NativeRect)); // Move the window to it's location, and resize User32Api.SetWindowPos(hwnd, IntPtr.Zero, lprNewRect.Left, lprNewRect.Top, lprNewRect.Width, lprNewRect.Height, WindowPos.SWP_NOZORDER | WindowPos.SWP_NOOWNERZORDER | WindowPos.SWP_NOACTIVATE); currentDpi = wParam.ToInt32() & 0xFFFF; // specify that the message was handled handled = true; break; case WindowsMessages.WM_PAINT: // This is a workaround for non DPI aware applications, these don't seem to get a WM_CREATE if (Math.Abs(Dpi) < double.Epsilon && !IsDpiAware) { isDpiMessage = true; currentDpi = GetDpi(hwnd); } break; case WindowsMessages.WM_SETICON: // This is a workaround for handling WinProc outside of the class if (_needsListenerWorkaround) { isDpiMessage = true; // disable workaround _needsListenerWorkaround = false; currentDpi = GetDpi(hwnd); } break; case WindowsMessages.WM_DESTROY: // If the window is destroyed, we complete the subject _onDpiChanged.OnCompleted(); break; } // Check if the DPI was changed, if so call the action (if any) if (!isDpiMessage) { return(IntPtr.Zero); } if (!IsEqual(Dpi, currentDpi)) { var beforeDpi = Dpi; Log.Verbose().WriteLine("Changing DPI from {0} to {1}", beforeDpi, currentDpi); _onDpiChangeInfo.OnNext(new DpiChangeInfo(DpiChangeEventTypes.Before, beforeDpi, currentDpi)); Dpi = currentDpi; _onDpiChanged.OnNext(Dpi); _onDpiChangeInfo.OnNext(new DpiChangeInfo(DpiChangeEventTypes.Change, beforeDpi, currentDpi)); _onDpiChangeInfo.OnNext(new DpiChangeInfo(DpiChangeEventTypes.After, beforeDpi, currentDpi)); } else { Log.Verbose().WriteLine("DPI was unchanged from {0}", Dpi); } return(IntPtr.Zero); }