Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        public void SetTopMost(bool isTopMost)
        {
            var topMostHandle = isTopMost ? HWnd.TopMost : HWnd.NoTopMost;

            User32Api.SetWindowPos(WindowHandle, topMostHandle, 0, 0, 0, 0,
                                   SetWindowPosFlags.IgnoreMove | SetWindowPosFlags.IgnoreResize);
        }
Esempio n. 3
0
        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);
            }
        }
Esempio n. 4
0
        /// <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);
            }
        }
Esempio n. 5
0
 /// <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);
 }
Esempio n. 6
0
        /// <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);
        }
Esempio n. 7
0
        /// <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);
        }