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;
}