Given that the question is tagged with C#, I took the information supplied by @Pavel Henrykhsen and @Stefnotch and formulated a solution in C#.
using System.Runtime.InteropServices;
while(true)
{
var focusAssistMode = Console.ReadLine() == "on" ? FocusAssistMode.Fullscreen : FocusAssistMode.Off;
var result = FocusAssistHelper.SetFocusAssistMode(focusAssistMode);
if (result == 0)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine($"Failed with error code {result}");
};
}
public static class FocusAssistHelper
{
[DllImport("ntdll.dll", SetLastError = true)]
static extern int ZwUpdateWnfStateData(
ref ulong StateName,
IntPtr Buffer,
int Length,
Guid TypeId,
IntPtr ExplicitScope,
uint MatchingChangeStamp,
bool CheckStamp
);
[DllImport("ntdll.dll", SetLastError = true)]
static extern int ZwQueryWnfStateData(
ref ulong StateName,
Guid TypeId,
IntPtr ExplicitScope,
out uint ChangeStamp,
IntPtr Buffer,
ref int BufferSize
);
const ulong WNF_SHEL_QUIET_MOMENT_SHELL_MODE_CHANGED = 0xd83063ea3bf5075UL;
public static int GetFocusAssistMode(out FocusAssistMode mode)
{
var stateName = WNF_SHEL_QUIET_MOMENT_SHELL_MODE_CHANGED;
int bufferSize = 4;
var bufferPtr = Marshal.AllocHGlobal(bufferSize);
var result = ZwQueryWnfStateData(ref stateName, Guid.Empty, IntPtr.Zero, out _, bufferPtr, ref bufferSize);
if (result == 0)
{
var modeAsByteArray = new byte[bufferSize];
Marshal.Copy(bufferPtr, modeAsByteArray, 0, modeAsByteArray.Length);
mode = (FocusAssistMode)BitConverter.ToUInt32(modeAsByteArray);
}
else
{
mode = FocusAssistMode.Off;
}
return result;
}
public static int SetFocusAssistMode(FocusAssistMode mode)
{
var stateName = WNF_SHEL_QUIET_MOMENT_SHELL_MODE_CHANGED;
var modeAsByteArray = BitConverter.GetBytes((uint)mode);
var bufferPtr = Marshal.AllocHGlobal(modeAsByteArray.Length);
try
{
Marshal.Copy(modeAsByteArray, 0, bufferPtr, modeAsByteArray.Length);
return ZwUpdateWnfStateData(ref stateName, bufferPtr, modeAsByteArray.Length, Guid.Empty, IntPtr.Zero, 0, false);
}
finally
{
Marshal.FreeHGlobal(bufferPtr);
}
}
}
public enum FocusAssistMode : uint
{
Off = 0,
Game = 1,
Fullscreen = 2,
}
Notes:
- Tested in Windows 10 22H2 19045.3803.
- Under Windows Focus Assist settings, either
When I'm duplicating my display
or When I'm playing a game
must be set to On
, depending on which mode you intend to activate programmatically.
- It seems like Windows keeps track of which process/app was responsible for activating Focus Assist. If it wasn't your app, you cannot turn it off (please let me know if you find a workaround).
- In order to turn Focus Assist on, you sometimes need to issue a command to turn it off first (even though it is already off). For best results, always turn off then on.