Example #1
0
        private static void RedrawWindowsSystemTrayArea()
        {
            try
            {
                // Windows XP and earlier
                IntPtr hNotificationArea = Native.FindWindowEx
                                           (
                    Native.FW(Native.FW(Native.FW(IntPtr.Zero, "Shell_TrayWnd"), "TrayNotifyWnd"), "SysPager"),
                    IntPtr.Zero,
                    "ToolbarWindow32",
                    "Notification Area"
                                           );

                // Windows Vista and later
                if ((hNotificationArea == IntPtr.Zero) || (hNotificationArea.ToInt32() == Native.INVALID_HANDLE_VALUE))
                {
                    hNotificationArea = Native.FindWindowEx
                                        (
                        Native.FW(Native.FW(Native.FW(IntPtr.Zero, "Shell_TrayWnd"), "TrayNotifyWnd"), "SysPager"),
                        IntPtr.Zero,
                        "ToolbarWindow32",
                        "User Promoted Notification Area"
                                        );
                }

                if ((hNotificationArea == IntPtr.Zero) || (hNotificationArea.ToInt32() == Native.INVALID_HANDLE_VALUE))
                {
                    return;
                }

                // Get the notification bounds
                Native.RECT rect = new Native.RECT();
                Native.GetClientRect(hNotificationArea, ref rect);

                // Wiggle the mouse over the notification area
                // Note: this doesn't actually move the mouse cursor on the screen -- this just sends a message to the system tray window
                //       that mouse movement occurred over it, forcing it to refresh.  Sending messages asking for a repaint or invalidated
                //       area don't work, but this does.
                for (UInt32 x = 0; x < rect.Right; x += 5)
                {
                    for (UInt32 y = 0; y < rect.Bottom; y += 5)
                    {
                        Native.SendMessage(hNotificationArea, Native.WM_MOUSEMOVE, 0, (y << 16) | x);
                    }
                }
            }
            catch { }
        }
        /// <summary>
        ///     remove the menu, resize the window, remove border, and maximize
        /// </summary>
        public static void MakeWindowBorderless(ProcessDetails processDetails, Forms.MainWindow frmMain, IntPtr targetWindow, Rectangle targetFrame, Favorites.Favorite favDetails)
        {
            // Automatically match a window to favorite details, if that information is available.
            // Note: if one is not available, the default settings will be used as a new Favorite() object.

            // Automatically match this window to a process

            // Failsafe to prevent rapid switching, but also allow a few changes to the window handle (to be persistent)
            if (processDetails != null)
                if (processDetails.MadeBorderless)
                    if ((processDetails.MadeBorderlessAttempts > 3) || (!processDetails.WindowHasTargetableStyles))
                        return;

            // If no target frame was specified, assume the entire space on the primary screen
            if ((targetFrame.Width == 0) || (targetFrame.Height == 0))
                targetFrame = Screen.FromHandle(targetWindow).Bounds;

            // Get window styles
            WindowStyleFlags styleCurrentWindow_standard = Native.GetWindowLong(targetWindow, WindowLongIndex.Style);
            WindowStyleFlags styleCurrentWindow_extended = Native.GetWindowLong(targetWindow, WindowLongIndex.ExtendedStyle);

            // Compute new styles (XOR of the inverse of all the bits to filter)
            WindowStyleFlags styleNewWindow_standard =
            (
                styleCurrentWindow_standard
             & ~(
                    WindowStyleFlags.Caption // composite of Border and DialogFrame
             //   | WindowStyleFlags.Border
             //   | WindowStyleFlags.DialogFrame                  
                  | WindowStyleFlags.ThickFrame
                  | WindowStyleFlags.SystemMenu
                  | WindowStyleFlags.MaximizeBox // same as TabStop
                  | WindowStyleFlags.MinimizeBox // same as Group
                )
            );

            WindowStyleFlags styleNewWindow_extended = 
            (
                styleCurrentWindow_extended
             & ~(
                    WindowStyleFlags.ExtendedDlgModalFrame
                  | WindowStyleFlags.ExtendedComposited
                  | WindowStyleFlags.ExtendedWindowEdge
                  | WindowStyleFlags.ExtendedClientEdge
                  | WindowStyleFlags.ExtendedLayered
                  | WindowStyleFlags.ExtendedStaticEdge
                  | WindowStyleFlags.ExtendedToolWindow
                  | WindowStyleFlags.ExtendedAppWindow
                )
            );

            // Should have process details by now
            if (processDetails != null)
            {
                // Save original details on this window so that we have a chance at undoing the process
                processDetails.OriginalStyleFlags_Standard = styleCurrentWindow_standard;
                processDetails.OriginalStyleFlags_Extended = styleCurrentWindow_extended;
                Native.RECT rect_temp = new Native.RECT();
                Native.GetWindowRect(processDetails.WindowHandle, out rect_temp);
                processDetails.OriginalLocation = new Rectangle(rect_temp.Left, rect_temp.Top, rect_temp.Right - rect_temp.Left, rect_temp.Bottom - rect_temp.Top);
            }

            // remove the menu and menuitems and force a redraw
            if (favDetails.RemoveMenus)
            {
                // unfortunately, menus can't be re-added easily so they aren't removed by default anymore
                IntPtr menuHandle = Native.GetMenu(targetWindow);
                if (menuHandle != IntPtr.Zero)
                {
                    int menuItemCount = Native.GetMenuItemCount(menuHandle);

                    for (int i = 0; i < menuItemCount; i++)
                        Native.RemoveMenu(menuHandle, 0, MenuFlags.ByPosition | MenuFlags.Remove);

                    Native.DrawMenuBar(targetWindow);
                }
            }

            // auto-hide the Windows taskbar (do this before resizing the window)
            if (favDetails.HideWindowsTaskbar)
            {
                Native.ShowWindow(frmMain.Handle, WindowShowStyle.ShowNoActivate);
                if (frmMain.WindowState == FormWindowState.Minimized)
                    frmMain.WindowState = FormWindowState.Normal;

                Manipulation.ToggleWindowsTaskbarVisibility(Tools.Boolstate.False);
            }

            // auto-hide the mouse cursor
            if (favDetails.HideMouseCursor)
                Manipulation.ToggleMouseCursorVisibility(frmMain, Tools.Boolstate.False);

            // update window styles
            Native.SetWindowLong(targetWindow, WindowLongIndex.Style,         styleNewWindow_standard);
            Native.SetWindowLong(targetWindow, WindowLongIndex.ExtendedStyle, styleNewWindow_extended);

            // update window position
            if (favDetails.SizeMode != Favorites.Favorite.SizeModes.NoChange)
            {
                if ((favDetails.SizeMode == Favorites.Favorite.SizeModes.FullScreen) || (favDetails.PositionW == 0) || (favDetails.PositionH == 0))
                {
                    // Set the window size to the biggest possible, using bounding adjustments
                    Native.SetWindowPos
                    (
                        targetWindow,
                        0,
                        targetFrame.X + favDetails.OffsetL,
                        targetFrame.Y + favDetails.OffsetT,
                        targetFrame.Width - favDetails.OffsetL + favDetails.OffsetR,
                        targetFrame.Height - favDetails.OffsetT + favDetails.OffsetB,
                        SetWindowPosFlags.ShowWindow | SetWindowPosFlags.NoOwnerZOrder | SetWindowPosFlags.NoSendChanging
                    );

                    // And auto-maximize
                    if (favDetails.ShouldMaximize)
                        Native.ShowWindow(targetWindow, WindowShowStyle.Maximize);
                }
                else
                {
                    // Set the window size to the exact position specified by the user
                    Native.SetWindowPos
                    (
                        targetWindow,
                        0,
                        favDetails.PositionX,
                        favDetails.PositionY,
                        favDetails.PositionW,
                        favDetails.PositionH,
                        SetWindowPosFlags.ShowWindow | SetWindowPosFlags.NoOwnerZOrder | SetWindowPosFlags.NoSendChanging
                    );
                }
            }

            // Set topmost
            if (favDetails.TopMost)
            {
                Native.SetWindowPos
                (
                    targetWindow,
                    Native.HWND_TOPMOST,
                    0,
                    0,
                    0,
                    0,
                    SetWindowPosFlags.ShowWindow | SetWindowPosFlags.NoMove | SetWindowPosFlags.NoSize | SetWindowPosFlags.NoSendChanging
                );
            }

            // Make a note that we attempted to make the window borderless
            if (processDetails != null)
            {
                processDetails.MadeBorderless = true;
                processDetails.MadeBorderlessAttempts++;
            }
		
            if (Program.Steam_Loaded)
                BorderlessGamingSteam.Achievement_Unlock(0);
		
            return;
        }
        private static void RedrawWindowsSystemTrayArea()
        {
            try
            {
                // Windows XP and earlier
                IntPtr hNotificationArea = Native.FindWindowEx
                (
                    Native.FW(Native.FW(Native.FW(IntPtr.Zero, "Shell_TrayWnd"), "TrayNotifyWnd"), "SysPager"),
                    IntPtr.Zero,
                    "ToolbarWindow32",
                    "Notification Area"
                );

                // Windows Vista and later
                if ((hNotificationArea == IntPtr.Zero) || (hNotificationArea.ToInt32() == Native.INVALID_HANDLE_VALUE))
                {
                    hNotificationArea = Native.FindWindowEx
                    (
                        Native.FW(Native.FW(Native.FW(IntPtr.Zero, "Shell_TrayWnd"), "TrayNotifyWnd"), "SysPager"),
                        IntPtr.Zero,
                        "ToolbarWindow32",
                        "User Promoted Notification Area"
                    );
                }

                if ((hNotificationArea == IntPtr.Zero) || (hNotificationArea.ToInt32() == Native.INVALID_HANDLE_VALUE))
                    return;

                // Get the notification bounds
                Native.RECT rect = new Native.RECT();
                Native.GetClientRect(hNotificationArea, ref rect);

                // Wiggle the mouse over the notification area
                // Note: this doesn't actually move the mouse cursor on the screen -- this just sends a message to the system tray window
                //       that mouse movement occurred over it, forcing it to refresh.  Sending messages asking for a repaint or invalidated
                //       area don't work, but this does.
                for (UInt32 x = 0; x < rect.Right; x += 5)
                    for (UInt32 y = 0; y < rect.Bottom; y += 5)
                        Native.SendMessage(hNotificationArea, Native.WM_MOUSEMOVE, 0, (y << 16) | x);
            }
            catch { }
        }
        public static void ToggleWindowsTaskbarVisibility(Tools.Boolstate forced = Tools.Boolstate.Indeterminate)
        {
            try
            {
                IntPtr hTaskBar = Native.FindWindow("Shell_TrayWnd", null);
                
                if ((hTaskBar.ToInt32() == Native.INVALID_HANDLE_VALUE) || (hTaskBar == IntPtr.Zero))
                    return;

                bool TaskBarIsCurrentlyVisible = Native.IsWindowVisible(hTaskBar);
                bool WantToMakeWindowsTaskbarVisible = (forced == Tools.Boolstate.True) ? true : (forced == Tools.Boolstate.False) ? false : !TaskBarIsCurrentlyVisible;

                // For forced modes, if the taskbar is already visible and we're requesting to show it, then do nothing
                if (WantToMakeWindowsTaskbarVisible && TaskBarIsCurrentlyVisible)
                    return;

                // For forced modes, if the taskbar is already hidden and we're requesting to hide it, then do nothing
                if (!WantToMakeWindowsTaskbarVisible && !TaskBarIsCurrentlyVisible)
                    return;

                // If we're hiding the taskbar, let's take some notes on the original screen desktop work areas
                if (!WantToMakeWindowsTaskbarVisible)
                {
                    foreach (Screen screen in Screen.AllScreens)
                    {
                        OriginalScreenInfo osi = new OriginalScreenInfo();
                        osi.screen = screen;
                        osi.workarea = new Native.RECT();
                        osi.workarea.Left = screen.WorkingArea.Left;
                        osi.workarea.Top = screen.WorkingArea.Top;
                        osi.workarea.Right = screen.WorkingArea.Right;
                        osi.workarea.Bottom = screen.WorkingArea.Bottom;
                        Manipulation.OriginalScreens.Add(osi);
                    }
                }

                // Show or hide the Windows taskbar
                Native.ShowWindow(hTaskBar, (WantToMakeWindowsTaskbarVisible) ? WindowShowStyle.ShowNoActivate : WindowShowStyle.Hide);

                // Keep track of the taskbar state so we don't let the user accidentally close Borderless Gaming
                Manipulation.WindowsTaskbarIsHidden = !WantToMakeWindowsTaskbarVisible;

                if (WantToMakeWindowsTaskbarVisible)
                {
                    // If we're showing the taskbar, let's restore the original screen desktop work areas...
                    foreach (OriginalScreenInfo osi in Manipulation.OriginalScreens)
                        Native.SystemParametersInfo(SPI.SPI_SETWORKAREA, 0, ref osi.workarea, SPIF.SPIF_SENDCHANGE);

                    // ...and then forget them (we don't need them anymore)
                    Manipulation.OriginalScreens.Clear();

                    // And we need to redraw the system tray in case tray icons from other applications did something while the
                    // taskbar was hidden.  Simulating mouse movement over the system tray seems to be the best way to get this
                    // done.
                    Manipulation.RedrawWindowsSystemTrayArea();
                }
                else
                {
                    // If we're hiding the taskbar, let's set the screen desktop work area over the entire screen so that 
                    // maximizing windows works as expected.
                    foreach (OriginalScreenInfo osi in Manipulation.OriginalScreens)
                    {
                        Native.RECT rect = new Native.RECT();
                        rect.Left = osi.screen.Bounds.Left;
                        rect.Top = osi.screen.Bounds.Top;
                        rect.Right = osi.screen.Bounds.Right;
                        rect.Bottom = osi.screen.Bounds.Bottom;
                        Native.SystemParametersInfo(SPI.SPI_SETWORKAREA, 0, ref rect, SPIF.SPIF_SENDCHANGE);

                        // Note: WinAPI SystemParametersInfo() will automatically determine which screen by the rectangle we pass in.
                        //       (it's not possible to specify which screen we're referring to directly)
                    }
                }
            }
            catch { }  
        }
Example #5
0
        /// <summary>
        ///     Catches the Hotkeys
        /// </summary>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == Native.WM_HOTKEY)
            {
                uint keystroke          = ((uint)m.LParam >> 16) & 0x0000FFFF;
                uint keystroke_modifier = ((uint)m.LParam)       & 0x0000FFFF;

                // Global hotkey to make a window borderless
                if ((keystroke == MakeBorderless_HotKey) && (keystroke_modifier == MakeBorderless_HotKeyModifier))
                {
                    // Find the currently-active window
                    IntPtr hCurrentActiveWindow = Native.GetForegroundWindow();

                    // Only if that window isn't Borderless Windows itself
                    if (hCurrentActiveWindow != this.Handle)
                    {
                        // Figure out the process details based on the current window handle
						ProcessDetails pd = controller.Processes.FromHandle(hCurrentActiveWindow);
						if (pd == null)
						{
							Task.WaitAll(controller.RefreshProcesses());
							pd = controller.Processes.FromHandle(hCurrentActiveWindow);
							if (pd == null)
								return;
						}
                        // If we have information about this process -and- we've already made it borderless, then reverse the process
						if (pd.MadeBorderless)
                            Manipulation.RestoreWindow(pd);
                        // Otherwise, this is a fresh request to remove the border from the current window
                        else
							this.controller.RemoveBorder(pd);
                    }

                    return; // handled the message, do not call base WndProc for this message
                }

                if ((keystroke == MouseHide_HotKey) && (keystroke_modifier == MouseHide_HotKeyModifier))
                {
                    Manipulation.ToggleMouseCursorVisibility(this);

                    return; // handled the message, do not call base WndProc for this message
                }

                if ((keystroke == MouseLock_HotKey) && (keystroke_modifier == 0))
                {
                    IntPtr hWnd = Native.GetForegroundWindow();

                    // get size of clientarea
                    Native.RECT rect = new Native.RECT();
                    Native.GetClientRect(hWnd, ref rect);

                    // get top,left point of clientarea
                    Native.POINTAPI p = new Native.POINTAPI { X = 0, Y = 0 };
                    Native.ClientToScreen(hWnd, ref p);

                    Rectangle clipRect = new Rectangle(p.X, p.Y, rect.Right - rect.Left, rect.Bottom - rect.Top);

                    Cursor.Clip = (Cursor.Clip.Equals(clipRect)) ? Rectangle.Empty : clipRect;

                    return; // handled the message, do not call base WndProc for this message
                }
            }

            base.WndProc(ref m);
        }
Example #6
0
        /// <summary>
        ///     remove the menu, resize the window, remove border, and maximize
        /// </summary>
        public static void MakeWindowBorderless(ProcessDetails processDetails, Forms.MainWindow frmMain, IntPtr targetWindow, Rectangle targetFrame, Favorites.Favorite favDetails)
        {
            // Automatically match a window to favorite details, if that information is available.
            // Note: if one is not available, the default settings will be used as a new Favorite() object.

            // Automatically match this window to a process

            // Failsafe to prevent rapid switching, but also allow a few changes to the window handle (to be persistent)
            if (processDetails != null)
            {
                if (processDetails.MadeBorderless)
                {
                    if ((processDetails.MadeBorderlessAttempts > 3) || (!processDetails.WindowHasTargetableStyles))
                    {
                        return;
                    }
                }
            }

            // If no target frame was specified, assume the entire space on the primary screen
            if ((targetFrame.Width == 0) || (targetFrame.Height == 0))
            {
                targetFrame = Screen.FromHandle(targetWindow).Bounds;
            }

            // Get window styles
            WindowStyleFlags styleCurrentWindow_standard = Native.GetWindowLong(targetWindow, WindowLongIndex.Style);
            WindowStyleFlags styleCurrentWindow_extended = Native.GetWindowLong(targetWindow, WindowLongIndex.ExtendedStyle);

            // Compute new styles (XOR of the inverse of all the bits to filter)
            WindowStyleFlags styleNewWindow_standard =
                (
                    styleCurrentWindow_standard
                    & ~(
                        WindowStyleFlags.Caption // composite of Border and DialogFrame
                        //   | WindowStyleFlags.Border
                        //   | WindowStyleFlags.DialogFrame
                        | WindowStyleFlags.ThickFrame
                        | WindowStyleFlags.SystemMenu
                        | WindowStyleFlags.MaximizeBox // same as TabStop
                        | WindowStyleFlags.MinimizeBox // same as Group
                        )
                );

            WindowStyleFlags styleNewWindow_extended =
                (
                    styleCurrentWindow_extended
                    & ~(
                        WindowStyleFlags.ExtendedDlgModalFrame
                        | WindowStyleFlags.ExtendedComposited
                        | WindowStyleFlags.ExtendedWindowEdge
                        | WindowStyleFlags.ExtendedClientEdge
                        | WindowStyleFlags.ExtendedLayered
                        | WindowStyleFlags.ExtendedStaticEdge
                        | WindowStyleFlags.ExtendedToolWindow
                        | WindowStyleFlags.ExtendedAppWindow
                        )
                );

            // Should have process details by now
            if (processDetails != null)
            {
                // Save original details on this window so that we have a chance at undoing the process
                processDetails.OriginalStyleFlags_Standard = styleCurrentWindow_standard;
                processDetails.OriginalStyleFlags_Extended = styleCurrentWindow_extended;
                Native.RECT rect_temp = new Native.RECT();
                Native.GetWindowRect(processDetails.WindowHandle, out rect_temp);
                processDetails.OriginalLocation = new Rectangle(rect_temp.Left, rect_temp.Top, rect_temp.Right - rect_temp.Left, rect_temp.Bottom - rect_temp.Top);
            }

            // remove the menu and menuitems and force a redraw
            if (favDetails.RemoveMenus)
            {
                // unfortunately, menus can't be re-added easily so they aren't removed by default anymore
                IntPtr menuHandle = Native.GetMenu(targetWindow);
                if (menuHandle != IntPtr.Zero)
                {
                    int menuItemCount = Native.GetMenuItemCount(menuHandle);

                    for (int i = 0; i < menuItemCount; i++)
                    {
                        Native.RemoveMenu(menuHandle, 0, MenuFlags.ByPosition | MenuFlags.Remove);
                    }

                    Native.DrawMenuBar(targetWindow);
                }
            }

            // auto-hide the Windows taskbar (do this before resizing the window)
            if (favDetails.HideWindowsTaskbar)
            {
                Native.ShowWindow(frmMain.Handle, WindowShowStyle.ShowNoActivate);
                if (frmMain.WindowState == FormWindowState.Minimized)
                {
                    frmMain.WindowState = FormWindowState.Normal;
                }

                Manipulation.ToggleWindowsTaskbarVisibility(Tools.Boolstate.False);
            }

            // auto-hide the mouse cursor
            if (favDetails.HideMouseCursor)
            {
                Manipulation.ToggleMouseCursorVisibility(frmMain, Tools.Boolstate.False);
            }

            // update window styles
            Native.SetWindowLong(targetWindow, WindowLongIndex.Style, styleNewWindow_standard);
            Native.SetWindowLong(targetWindow, WindowLongIndex.ExtendedStyle, styleNewWindow_extended);

            // update window position
            if (favDetails.SizeMode != Favorites.Favorite.SizeModes.NoChange)
            {
                if ((favDetails.SizeMode == Favorites.Favorite.SizeModes.FullScreen) || (favDetails.PositionW == 0) || (favDetails.PositionH == 0))
                {
                    // Set the window size to the biggest possible, using bounding adjustments
                    Native.SetWindowPos
                    (
                        targetWindow,
                        0,
                        targetFrame.X + favDetails.OffsetL,
                        targetFrame.Y + favDetails.OffsetT,
                        targetFrame.Width - favDetails.OffsetL + favDetails.OffsetR,
                        targetFrame.Height - favDetails.OffsetT + favDetails.OffsetB,
                        SetWindowPosFlags.ShowWindow | SetWindowPosFlags.NoOwnerZOrder
                    );

                    // And auto-maximize
                    if (favDetails.ShouldMaximize)
                    {
                        Native.ShowWindow(targetWindow, WindowShowStyle.Maximize);
                    }
                }
                else
                {
                    // Set the window size to the exact position specified by the user
                    Native.SetWindowPos
                    (
                        targetWindow,
                        0,
                        favDetails.PositionX,
                        favDetails.PositionY,
                        favDetails.PositionW,
                        favDetails.PositionH,
                        SetWindowPosFlags.ShowWindow | SetWindowPosFlags.NoOwnerZOrder
                    );
                }
            }

            // Set topmost
            if (favDetails.TopMost)
            {
                Native.SetWindowPos
                (
                    targetWindow,
                    Native.HWND_TOPMOST,
                    0,
                    0,
                    0,
                    0,
                    SetWindowPosFlags.ShowWindow | SetWindowPosFlags.NoMove | SetWindowPosFlags.NoSize
                );
            }

            // Make a note that we attempted to make the window borderless
            if (processDetails != null)
            {
                processDetails.MadeBorderless = true;
                processDetails.MadeBorderlessAttempts++;
            }
            return;
        }
Example #7
0
        public static void ToggleWindowsTaskbarVisibility(Tools.Boolstate forced = Tools.Boolstate.Indeterminate)
        {
            try
            {
                IntPtr hTaskBar = Native.FindWindow("Shell_TrayWnd", null);

                if ((hTaskBar.ToInt32() == Native.INVALID_HANDLE_VALUE) || (hTaskBar == IntPtr.Zero))
                {
                    return;
                }

                bool TaskBarIsCurrentlyVisible       = Native.IsWindowVisible(hTaskBar);
                bool WantToMakeWindowsTaskbarVisible = (forced == Tools.Boolstate.True) ? true : (forced == Tools.Boolstate.False) ? false : !TaskBarIsCurrentlyVisible;

                // For forced modes, if the taskbar is already visible and we're requesting to show it, then do nothing
                if (WantToMakeWindowsTaskbarVisible && TaskBarIsCurrentlyVisible)
                {
                    return;
                }

                // For forced modes, if the taskbar is already hidden and we're requesting to hide it, then do nothing
                if (!WantToMakeWindowsTaskbarVisible && !TaskBarIsCurrentlyVisible)
                {
                    return;
                }

                // If we're hiding the taskbar, let's take some notes on the original screen desktop work areas
                if (!WantToMakeWindowsTaskbarVisible)
                {
                    foreach (Screen screen in Screen.AllScreens)
                    {
                        OriginalScreenInfo osi = new OriginalScreenInfo();
                        osi.screen          = screen;
                        osi.workarea        = new Native.RECT();
                        osi.workarea.Left   = screen.WorkingArea.Left;
                        osi.workarea.Top    = screen.WorkingArea.Top;
                        osi.workarea.Right  = screen.WorkingArea.Right;
                        osi.workarea.Bottom = screen.WorkingArea.Bottom;
                        Manipulation.OriginalScreens.Add(osi);
                    }
                }

                // Show or hide the Windows taskbar
                Native.ShowWindow(hTaskBar, (WantToMakeWindowsTaskbarVisible) ? WindowShowStyle.ShowNoActivate : WindowShowStyle.Hide);

                // Keep track of the taskbar state so we don't let the user accidentally close Borderless Gaming
                Manipulation.WindowsTaskbarIsHidden = !WantToMakeWindowsTaskbarVisible;

                if (WantToMakeWindowsTaskbarVisible)
                {
                    // If we're showing the taskbar, let's restore the original screen desktop work areas...
                    foreach (OriginalScreenInfo osi in Manipulation.OriginalScreens)
                    {
                        Native.SystemParametersInfo(SPI.SPI_SETWORKAREA, 0, ref osi.workarea, SPIF.SPIF_SENDCHANGE);
                    }

                    // ...and then forget them (we don't need them anymore)
                    Manipulation.OriginalScreens.Clear();

                    // And we need to redraw the system tray in case tray icons from other applications did something while the
                    // taskbar was hidden.  Simulating mouse movement over the system tray seems to be the best way to get this
                    // done.
                    Manipulation.RedrawWindowsSystemTrayArea();
                }
                else
                {
                    // If we're hiding the taskbar, let's set the screen desktop work area over the entire screen so that
                    // maximizing windows works as expected.
                    foreach (OriginalScreenInfo osi in Manipulation.OriginalScreens)
                    {
                        Native.RECT rect = new Native.RECT();
                        rect.Left   = osi.screen.Bounds.Left;
                        rect.Top    = osi.screen.Bounds.Top;
                        rect.Right  = osi.screen.Bounds.Right;
                        rect.Bottom = osi.screen.Bounds.Bottom;
                        Native.SystemParametersInfo(SPI.SPI_SETWORKAREA, 0, ref rect, SPIF.SPIF_SENDCHANGE);

                        // Note: WinAPI SystemParametersInfo() will automatically determine which screen by the rectangle we pass in.
                        //       (it's not possible to specify which screen we're referring to directly)
                    }
                }
            }
            catch { }
        }