我想在我的 C# WPF 项目中实现一项功能,在应用程序中,用户可以使用复选框打开/关闭焦点辅助(Windows 10 中的设置),该复选框会自动将焦点辅助设置切换为“打开”,或者如果取消选中“关闭”。
如果可能的话,我不想打开“聚焦辅助”窗口让用户手动单击开/关。
我尝试搜索如何能够控制这些设置,我所能找到的就是实现类
Windows.System
,但是,唯一的控件似乎是Windows.System.RemoteDesktop
,Windows.System.Power
,Windows.System.Display
和缺少FocusAssist
。
有人能指出我正确的方向吗?
我想出了以下内容。在 Windows 10 22H2 19045.3803 中测试。
备注:
在 Windows Focus Assist 设置下,必须将
When I'm duplicating my display
或 When I'm playing a game
设置为 On
,具体取决于您打算以编程方式激活的模式。
Windows 似乎会跟踪哪个进程/应用程序负责激活 Focus Assist。如果这不是您的应用程序,则无法将其关闭(如果您找到解决方法,请告诉我)。
为了打开聚焦辅助,您有时需要先发出命令将其关闭(即使它已经关闭)。为了获得最佳效果,请始终关闭然后再打开。
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
);
const ulong WNF_SHEL_QUIET_MOMENT_SHELL_MODE_CHANGED = 0xd83063ea3bf5075UL;
public static int SetFocusAssistMode(FocusAssistMode mode)
{
var modeAsByteArray = BitConverter.GetBytes((uint)mode);
var bufferPtr = Marshal.AllocHGlobal(modeAsByteArray.Length);
try
{
Marshal.Copy(modeAsByteArray, 0, bufferPtr, modeAsByteArray.Length);
var stateName = WNF_SHEL_QUIET_MOMENT_SHELL_MODE_CHANGED;
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,
}