使用uiAccess = True安装桌面WPF应用程序时的注意事项

Ada*_*her 9 .net c# wpf uipi ui-automation

背景:

我需要在另一台显示器上创建调光效果.我想我通过使用WPF窗口解决了这个问题,该窗口占用了整个屏幕尺寸TopmostAllowsTransparency=.它具有内部黑色发光效果,并且具有WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW应用于其中的样式(以及其他内容),以允许用户点击其后面的应用程序.

我监视EVENT_OBJECT_REORDERWindows 中的事件并调用SetWindowPos强制Topmost状态高于其他Topmost窗口.到目前为止,我的概念测试证明似乎运作良好.

我发现的问题是这个调光(窗口)会覆盖任务栏,但是如果我单击开始菜单则不会.我目前正在使用Windows 10进行测试.如果单击"开始"菜单,则会导致"开始"菜单和任务栏显示在调光(窗口)上方.我希望一切都保持黯淡.

我通过uiAccess在应用程序清单中设置= true 来解决此问题,生成自签名证书,并将exe复制到"c:\ program files*".这允许我强制窗口的最顶级状态,甚至在开始菜单上方.

我的问题:

  • 有没有办法在没有开始菜单的情况下定位窗口uiAccess?或者甚至是另一种在不使用窗口的情况下强制屏幕昏暗(但不依赖于显示器驱动程序或硬件功能)的方法?

  • 如果没有,在分发WPF应用程序(通过WiX安装项目或类似的东西)时,我需要注意什么,以绕过UIPI限制uiAccess= True?我可以在安装过程中简单地安装自签名证书吗?用户是否会遇到任何其他障碍?作为一名开发人员,在构建此问题时,我是否会遇到任何其他障碍(除了我已经提到过的内容)?

谢谢!

Fri*_*Guy 3

这不会回答任何关于 的问题uiAccess=true,但是...

调暗屏幕

作为调暗屏幕的另一种方法,您可以尝试使用SetDeviceGammaRamp一次调暗所有屏幕(如果需要)。

例如,采用以下辅助类:

/// <summary> Allows changing the gamma of the displays. </summary>
public static class GammaChanger
{
  /// <summary>
  ///  Retrieves the current gamma ramp data so that it can be restored later.
  /// </summary>
  /// <param name="gamma"> [out] The current gamma. </param>
  /// <returns> true if it succeeds, false if it fails. </returns>
  public static bool GetCurrentGamma(out GammaRampRgbData gamma)
  {
    gamma = GammaRampRgbData.Create();
    return GetDeviceGammaRamp(GetDC(IntPtr.Zero), ref gamma);
  }

  public static bool SetGamma(ref GammaRampRgbData gamma)
  {
    // Now set the value.
    return SetDeviceGammaRamp(GetDC(IntPtr.Zero), ref gamma);
  }

  public static bool SetBrightness(int gamma)
  {
    GammaRampRgbData data = new GammaRampRgbData
                            {
                              Red = new ushort[256],
                              Green = new ushort[256],
                              Blue = new ushort[256]
                            };

    int wBrightness = gamma; // reduce the brightness
    for (int ik = 0; ik < 256; ik++)
    {
      int iArrayValue = ik * (wBrightness + 128);
      if (iArrayValue > 0xffff)
      {
        iArrayValue = 0xffff;
      }
      data.Red[ik] = (ushort)iArrayValue;
      data.Green[ik] = (ushort)iArrayValue;
      data.Blue[ik] = (ushort)iArrayValue;
    }

    return SetGamma(ref data);
  }

  [DllImport("gdi32.dll")]
  private static extern bool SetDeviceGammaRamp(IntPtr hdc, ref GammaRampRgbData gammaRgbArray);

  [DllImport("gdi32.dll")]
  private static extern bool GetDeviceGammaRamp(IntPtr hdc, ref GammaRampRgbData gammaRgbArray);

  [DllImport("user32.dll")]
  private static extern IntPtr GetDC(IntPtr hWnd);

  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
  public struct GammaRampRgbData
  {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public UInt16[] Red;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public UInt16[] Green;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public UInt16[] Blue;

    /// <summary> Creates a new, initialized GammaRampRgbData object. </summary>
    /// <returns> A GammaRampRgbData. </returns>
    public static GammaRampRgbData Create()
    {
      return new GammaRampRgbData
             {
               Red = new ushort[256],
               Green = new ushort[256],
               Blue = new ushort[256]
             };
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

结合a中的以下内容static void Main(),程序将改变亮度,直到用户退出应用程序:

GammaChanger.GammaRampRgbData originalGamma;
bool success = GammaChanger.GetCurrentGamma(out originalGamma);
Console.WriteLine($"Originally: {success}");

success = GammaChanger.SetBrightness(44);
Console.WriteLine($"Setting: {success}");

Console.ReadLine();

success = GammaChanger.SetGamma(ref originalGamma);
Console.WriteLine($"Restoring: {success}");

Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)

但请注意,这是将全局解决方案应用于局部问题

如果您确实走这条路,我建议您在退出之前确保恢复用户的伽玛值,否则他们将获得不太好的体验,即您的应用程序崩溃并且屏幕不会永久变暗。

资料来源: