public void Draw(Pair <VirtualDesktop, HMONITOR> key) { ObservableCollection <DesktopWindow> windows = Windows[key]; KeyValuePair <Pair <VirtualDesktop, HMONITOR>, ObservableCollection <DesktopWindow> > desktopMonitor = new KeyValuePair <Pair <VirtualDesktop, HMONITOR>, ObservableCollection <DesktopWindow> >(key, windows); float ScreenScalingFactorVert; int mX, mY; IEnumerable <Rectangle> gridGenerator; DrawMonitor(desktopMonitor, out ScreenScalingFactorVert, out mX, out mY, out gridGenerator); HDWP hDWP1 = User32.BeginDeferWindowPos(windows.Count); foreach (var w in desktopMonitor.Value.Select((value, i) => new Tuple <int, DesktopWindow>(i, value))) { Rectangle adjustedSize = new Rectangle( gridGenerator.ToArray()[w.Item1].X, gridGenerator.ToArray()[w.Item1].Y, gridGenerator.ToArray()[w.Item1].Width, gridGenerator.ToArray()[w.Item1].Height ); User32.ShowWindow(w.Item2.Window, ShowWindowCommand.SW_RESTORE); DrawWindow1(ScreenScalingFactorVert, mX, mY, adjustedSize, w, hDWP1); } User32.EndDeferWindowPos(hDWP1.DangerousGetHandle()); HDWP hDWP2 = User32.BeginDeferWindowPos(windows.Count); foreach (var w in desktopMonitor.Value.Select((value, i) => new Tuple <int, DesktopWindow>(i, value))) { Rectangle adjustedSize = new Rectangle( gridGenerator.ToArray()[w.Item1].X, gridGenerator.ToArray()[w.Item1].Y, gridGenerator.ToArray()[w.Item1].Width, gridGenerator.ToArray()[w.Item1].Height ); DrawWindow2(ScreenScalingFactorVert, mX, mY, adjustedSize, w, hDWP2); } User32.EndDeferWindowPos(hDWP2.DangerousGetHandle()); foreach (var w in desktopMonitor.Value.Select((value, i) => new Tuple <int, DesktopWindow>(i, value))) { w.Item2.GetWindowInfo(); } }
public void Draw() { foreach (var desktopMonitor in Windows) { float ScreenScalingFactorVert; int mX, mY; IEnumerable <Rectangle> gridGenerator; DrawMonitor(desktopMonitor, out ScreenScalingFactorVert, out mX, out mY, out gridGenerator); HDWP hDWP1 = User32.BeginDeferWindowPos(Windows.Count); foreach (var w in desktopMonitor.Value.Select((value, i) => new Tuple <int, DesktopWindow>(i, value))) { Rectangle adjustedSize = new Rectangle( gridGenerator.ToArray()[w.Item1].X, gridGenerator.ToArray()[w.Item1].Y, gridGenerator.ToArray()[w.Item1].Width, gridGenerator.ToArray()[w.Item1].Height ); User32.ShowWindow(w.Item2.Window, ShowWindowCommand.SW_RESTORE); DrawWindow1(ScreenScalingFactorVert, mX, mY, adjustedSize, w, hDWP1); } User32.EndDeferWindowPos(hDWP1.DangerousGetHandle()); HDWP hDWP2 = User32.BeginDeferWindowPos(Windows.Count); foreach (var w in desktopMonitor.Value.Select((value, i) => new Tuple <int, DesktopWindow>(i, value))) { Rectangle adjustedSize = new Rectangle( gridGenerator.ToArray()[w.Item1].X, gridGenerator.ToArray()[w.Item1].Y, gridGenerator.ToArray()[w.Item1].Width, gridGenerator.ToArray()[w.Item1].Height ); DrawWindow2(ScreenScalingFactorVert, mX, mY, adjustedSize, w, hDWP2); } User32.EndDeferWindowPos(hDWP2.DangerousGetHandle()); foreach (var w in desktopMonitor.Value.Select((value, i) => new Tuple <int, DesktopWindow>(i, value))) { w.Item2.GetWindowInfo(); } } }
/// <summary> /// Reposition/resize a set of windows, or change their visiblity. When changing visibilty, windows can't be repositioned/resized. /// This is a limitation of the underlying Win32 API. /// </summary> /// <remarks> /// When invalid window handles are passed, they are simply ignored. /// </remarks> /// <param name="windows">The windows to perform the operation on.</param> /// <param name="changeZOrder"> /// When true and changeVisibility is not set, the windows's Z orders are changed to reflect the order of the toPosition list. /// The first item in the list will appear at the top, while the last item will appear at the bottom. /// </param> /// <param name="changeVisibility">When set to true only the visiblity of windows can be changed. When set to false, only the other parameters can be changed.</param> static void RepositionWindowsInner(ICollection <RepositionWindowInfo> windows, bool changeZOrder, bool changeVisibility) { if (windows.Count == 0) { // Nothing to reposition. return; } bool succeeded = false; var windowList = windows.ToList(); while (!succeeded) { IntPtr windowsPositionInfo = User32.BeginDeferWindowPos(windowList.Count); bool errorEncountered = false; for (int i = 0; i < windowList.Count; ++i) { RepositionWindowInfo window = windowList[i]; // Activating windows is outside of the scope of this function, otherwise it gets too complex. var commands = User32.DeferWindowPosCommands.NoActivate; if (changeVisibility && window.HasVisibilityChanged()) { commands |= window.Visible ? User32.DeferWindowPosCommands.ShowWindow : User32.DeferWindowPosCommands.HideWindow; } if (changeVisibility || !window.HasSizeChanged()) { commands |= User32.DeferWindowPosCommands.NoResize; } if (changeVisibility || !window.HasPositionChanged()) { commands |= User32.DeferWindowPosCommands.NoMove; } if (changeVisibility || (i == 0 || !changeZOrder)) { commands |= User32.DeferWindowPosCommands.NoZOrder; commands |= User32.DeferWindowPosCommands.NoOwnerZOrder; } windowsPositionInfo = User32.DeferWindowPos( windowsPositionInfo, window.ToPosition.Handle, i == 0 ? IntPtr.Zero : windowList[i - 1].ToPosition.Handle, window.X, window.Y, window.Width, window.Height, commands); // Handle possible errors. if (windowsPositionInfo == IntPtr.Zero) { var error = (ErrorCode)Marshal.GetLastWin32Error(); switch (error) { case ErrorCode.InvalidWindowHandle: windowList = windowList.Where(w => !w.ToPosition.IsDestroyed()).ToList(); break; case ErrorCode.InvalidMultipleWindowPositionStructure: // Nothing to do, EndDeferWindowPos will fail, and a new operation will be attempted. break; case ErrorCode.AccessDenied: windowList.RemoveAt(i); break; } // Try again starting over with a new iteration. errorEncountered = true; break; } } if (!errorEncountered) { succeeded = User32.EndDeferWindowPos(windowsPositionInfo); if (succeeded && User32.GetActiveWindow() == IntPtr.Zero) { // All windows are hidden and there is no more active window. // This causes a bug next time a window is shown which doesn't show up on the taskbar. Another window is shown on the taskbar, but not made visible. // To prevent this, activate the start bar. WindowInfo startBar = GetWindows().FirstOrDefault(w => w.GetClassName() == "Shell_TrayWnd"); if (startBar != null) { startBar.SetForegroundWindow(); } } } } }