Processing Ajax...

Title
Close Dialog

Message

Confirm
Close Dialog

Confirm
Close Dialog

Focus game and make it borderless windowed

Description
This scripted function will focus the specified game window and make it borderless full screen. Note that there are some configuration steps in the comments near the top of the script.
Language
C#.net
Minimum Version
Created By
John Schewe89611
Contributors
-
Date Created
Oct 30, 2020
Date Last Modified
Oct 30, 2020

Scripted Function (Macro) Code

using System;
using System.Drawing;
using System.Runtime.InteropServices;

//////////////////////////////////////
// Instructions for setup:
//////////////////////////////////////
//
// 1. Make a trigger to this script with the event 'Window Focused' and process name *.*
//
// 2. Set the primary monitor split: [Advanced Settings] > [Monitor Configuration] > [Force Primary Monitor ID]
// 
// 3. Add Game window trigger criteria below
//
// 4. In each game set the display mode to 'Windowed'
//
//////////////////////////////////////
public static class DisplayFusionFunction
{
	public static bool IsGameWindow(IntPtr hwnd)
	{
		var exePath = BFS.Application.GetMainFileByWindow(hwnd);
		var wndTitle = BFS.Window.GetText(hwnd);
		
		// these are the trigger match criteria to determine what windows count as game windows to this script
		// if using a DisplayFocus trigger to activate this script, then choose 'Window Focused' and *.*
		return 
			(exePath.EndsWith(@"Deep Rock Galactic\FSD\Binaries\Win64\FSD-Win64-Shipping.exe") && wndTitle == "Deep Rock Galactic") ||
			(exePath.EndsWith("SpaceEngineers.exe") && wndTitle == "Space Engineers") ||
			// Space Engineers: also to fix video render resolution to match window size:
			//     edit %APPDATA%\SpaceEngineers\SpaceEngineers.cfg
			//     find <Key>ScreenWidth</Key> and <Key>ScreenHeight</Key>
			//     set their values to the appropriate numbers
			(exePath.EndsWith("Hearthstone.exe") && wndTitle == "Hearthstone") ||
			(exePath.EndsWith("Risk of Rain 2.exe") && wndTitle == "Risk of Rain 2");
	}
	
	public static void Run(IntPtr hwnd)
	{
		string oldFocus = BFS.ScriptSettings.ReadValue("GameWindowFocus");
		long oldHwnd;
		
		if (oldFocus != null && oldFocus.Length > 0 && long.TryParse(oldFocus, out oldHwnd) && oldHwnd != 0 && (IntPtr)oldHwnd != hwnd)
            GameUnfocus((IntPtr)oldHwnd);
            
        if (IsGameWindow(hwnd))
            GameFocus(hwnd);
	}
	
	private static void GameFocus(IntPtr hwnd)
	{
		// adjust window style
		var wndStyle = BFS.Window.GetWindowStyle(hwnd);
        var newStyle = wndStyle & ~(
            BFS.WindowEnum.WindowStyle.WS_CAPTION | 
            BFS.WindowEnum.WindowStyle.WS_SYSMENU |
            BFS.WindowEnum.WindowStyle.WS_THICKFRAME__SIZEBOX |
            BFS.WindowEnum.WindowStyle.WS_MINIMIZEBOX |
            BFS.WindowEnum.WindowStyle.WS_MAXIMIZEBOX
        );
        if (wndStyle != newStyle)
            BFS.Window.SetWindowStyle(newStyle, hwnd);
		
		// get primary screen
		// DON'T FORGET to set [Advanced Settings] > [Monitor Configuration] > [Force Primary Monitor ID]
		// to   {monitor_id}.{split_id}   if you want a specific split to act as the primary
		var bnds = BFS.Monitor.GetPrimaryMonitorBounds();
		
		int posFlags = 0;
		if (BFS.Window.HasWindowStyleEx(BFS.WindowEnum.WindowStyleEx.WS_EX_TOPMOST, hwnd))
            posFlags |= SWP_NOZORDER;
        var wndBnds = BFS.Window.GetBounds(hwnd);
        if (wndBnds.X == bnds.X && wndBnds.Y == bnds.Y)
            posFlags |= SWP_NOMOVE;
        if (wndBnds.Width == bnds.Width && wndBnds.Height == bnds.Height)
            posFlags |= SWP_NOSIZE;
		
		// we use win32 command directly because BFS.Window.SetSize doesn't seem to work properly with the above window styles
		// plus it's a bit cleaner (less screen flashing) to do everything in one function call
		if (SetWindowPos(hwnd, HWND_TOPMOST, bnds.X, bnds.Y, bnds.Width, bnds.Height, posFlags))
		
            // save it to allow unfocusing later
            BFS.ScriptSettings.WriteValue("GameWindowFocus", hwnd.ToString());
	}
	
	private static void GameUnfocus(IntPtr hwnd)
	{
		int posFlags = SWP_NOMOVE | SWP_NOSIZE;
		if (!BFS.Window.HasWindowStyleEx(BFS.WindowEnum.WindowStyleEx.WS_EX_TOPMOST, hwnd))
            posFlags |= SWP_NOZORDER;
		
		SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, posFlags);
		
		// clear save
		BFS.ScriptSettings.WriteValue("GameWindowFocus", null);
	}
	
    [DllImport("user32.dll")]
    static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
    
    const int HWND_TOPMOST = -1;
    const int HWND_NOTOPMOST = -2;
    
    const int SWP_NOMOVE = 0X2;
    const int SWP_NOSIZE = 1;
    const int SWP_NOZORDER = 0X4;
    const int SWP_SHOWWINDOW = 0x0040;
}