【问题标题】:How to determine programmatically the Windows' Performance settings with Delphi 2010如何使用 Delphi 2010 以编程方式确定 Windows 的性能设置
【发布时间】:2012-12-17 10:59:28
【问题描述】:

下面的代码是关闭我的应用程序。

procedure TfrmMain.btnClose1Click(Sender: TObject);
var
  i : Integer;
begin
  for i := 255 downto 0 do begin
    frmMain.AlphaBlendValue := i;
    application.ProcessMessages;
  end;

  Close;
end;

Windows 性能设置为“让 Windows 选择...”

  • 使用上述代码关闭我的 Delphi 应用程序时,褪色几乎是 瞬时(最多可能 ¼ 秒,如果我眨眼我会错过 过渡)。

如果我将性能选项设置为“调整以获得最佳性能”

  • 退出同一个应用程序时,淡入淡出需要 12 秒。
  • 使用相同的代码但注释掉 AlphaBlendValue 更改可以消除延迟。

我在 Delphi 2010 和 DelphiXE2 上都对此进行了测试,结果是相同的。 如果这有什么不同的话,这是在 Windows 7 Ultimate 64bit 上测试的。

至少可以说这种行为让我感到困惑。

  • 我认为 forms Alpha 属性由 GPU 处理,因此不会受到旨在最大化 CPU 性能的 Windows 性能设置的影响。

因此,就这一点而言,我不确定这是 Windows 7 错误、Delphi 错误还是只是我缺乏知识。

至于修复... 有没有办法判断 Windows 是否在垃圾图形/最大性能模式下运行,以便我可以在我的应用程序中禁用 Alpha 渐变效果?


为清楚起见进行编辑: 虽然我想修复淡入淡出,但我真正想要的是一种确定 Windows 性能设置的方法。

我正在寻找如何确定特定的 Windows 设置 - 当您进入 Windows 性能选项时,有 3 个选项卡。在第一个选项卡“视觉效果”上有 3 个预设选项和第 4 个选项用于“自定义”。至少我试图确定选择的选项是否是“调整以获得最佳性能”,如果我可以更好地确定此选项卡上的设置。


感谢任何帮助。

【问题讨论】:

    标签: windows delphi winapi delphi-2010


    【解决方案1】:

    您的代码的根本问题是,无论机器的性能特征如何,您都在强制执行 256 次不同的更新。您不必使用 255 和 0 之间的每一个 alpha 混合值。您可以跳过一些值并仍然具有平滑的淡入淡出。

    您需要考虑机器的实际图形性能。由于您无法预测,因此您应该在淡入淡出代码中考虑实时。无论您的机器性能如何,这样做都会为您提供一致的褪色率。

    所以,这里有一个简单的例子来演示将淡入淡出率与实时联系起来:

    procedure TfrmMain.btnClose1Click(Sender: TObject);
    var
      Stopwatch: TStopwatch;
      NewAlphaBlendValue: Integer;
    begin
      Stopwatch := TStopwatch.StartNew;
      while True do
      begin
        NewAlphaBlendValue := 255-(Stopwatch.ElapsedMilliseconds div 4);
        if NewAlphaBlendValue>0 then
          AlphaBlendValue := NewAlphaBlendValue
        else
          break;
      end;
      Close;
    end;
    

    淡入淡出的持续时间为 1 秒。您可以轻松地调整数学以根据您的要求修改持续时间。即使在性能不佳的机器上,此代码也会产生平滑的淡入淡出。

    我还要评论说,您不应该在 TfrmMain 方法中使用全局变量 drmMainTfrmMain 方法已经可以访问该实例。它是Self。当然你可以省略Self。更重要的是,拨打ProcessMessages 很糟糕。这允许对排队的输入消息进行重入处理。你不希望这种情况发生。所以删除对ProcessMessages的调用。


    您实际上询问了检测调整以获得最佳性能设置。但我认为这是一个错误的问题。首先,您应该修复淡化代码,以便淡化持续时间与图形性能无关。

    完成此操作后,如果用户要求较低质量的外观设置,您可能仍希望禁用淡入淡出。我认为您不应该寻找您提到的 3 个罐装选项之一。它们很可能是特定于 Windows 版本的。就个人而言,我会在最小化和最大化设置时基于 Animate 窗口 设置的行为。我的理由是,如果用户不希望最小化和最大化动画,那么大概他们不希望关闭窗口被淡化。

    以下是读取该设置的方法:

    function GetWindowAnimation: Boolean;
    var
      AnimationInfo: TAnimationInfo;
    begin
      AnimationInfo.cbSize := SizeOf(AnimationInfo);
      if not SystemParametersInfo(SPI_GETANIMATION, AnimationInfo.cbSize,
          @AnimationInfo, 0) then
        RaiseLastOSError;
      Result := AnimationInfo.iMinAnimate<>0;
    end;
    

    我认为您可能关心的大多数其他设置也可以使用SystemParametersInfo 读取。您应该能够通过关注documentation 了解如何操作。

    【讨论】:

    • Windows 没有原生的 Windows 动画 API 吗?
    • 如果我想要淡入淡出,计时 cmets 是有效的。如果我知道用户的系统以提到的方式“优化”了,那么我会完全跳过淡入淡出,因为它总是看起来很糟糕。 “性能”设置存储在某处或派生问题是如何确定它。
    • @Arioch'有AnimateWindow()支持淡入淡出
    • 我明白你在说什么,但你不明白我在问什么。我不是在尝试预测 Windows 性能,而是在寻找如何确定特定的 Windows 设置 - 当您进入 Windows 性能选项时,有 3 个选项卡。在第一个选项卡“视觉效果”上有 3 个预设选项和第 4 个选项用于“自定义”。至少我试图确定选择的选项是否是“调整以获得最佳性能”,如果我可以更好地确定此选项卡上的设置。
    • >>我只是认为我的解决方案更好
    【解决方案2】:

    对于迟到的后续行动感到抱歉,但我花了一段时间才弄清楚我的问题及其背后的一些问题的有效答案。

    首先,感谢 David Heffernan 提供了有关处理淡入淡出循环的更好方法的见解以及来自 Delphi 诊断单元的 TStopWatch 功能信息,非常感谢。

    关于能够确定 Windows 的性能设置...

    当使用以下未优化的淡入淡出循环时

    procedure TfrmMain.btnFadeNCloseClick(Sender: TObject);
    var
      i : Integer;
    begin
      for i := 255 downto 0 do 
        frmMain.AlphaBlendValue := i;
    
      Close;
    end;
    

    导致性能问题的实际 Windows 性能选项设置是“启用桌面合成”和“使用视觉Windows 和按钮上的样式"。如果启用了这两个选项,则没有问题,如果未启用任何一个设置,则循环抓取**(如果表单最大化,我的系统上大约需要 12 秒)。

    事实证明,打开或关闭 Aero Glass 会影响这两个相同的设置。因此,能够检测 Aero Glass 是否打开使我能够确定是否在我的应用程序中启用表单效果,例如过渡淡入淡出和其他吸引眼球的效果。另外,现在我还可以在我的错误报告中捕获这些信息。

    **请注意,这似乎是一个 NVidia 问题/错误,或者至少是一个在配备 NVidia 显卡的系统上更为严重的问题。在 2 不同的 NVidia 系统(带有最新的,如果不是最新的驱动程序)我 混合形式的淡入淡出得到了类似的结果 - 小于 如果 Aero Glass 开启,0.001 秒,如果 Aero Glass 开启,大约 12 秒 离开。在带有 Intel 显卡的系统上 - 少于 0.001 秒 如果 Aero Glass 打开,如果 Aero Glass 关闭,大约需要 3.7 秒。现在 授予我的测试样本很小,3 个 NVidia 系统(算上我的 最初报告问题的客户)和一个非 NVidia 系统 但如果我使用的是不错的 NVidia 显卡,我不会打扰 关闭 Aero Glass。

    下面是检测是否通过 Delphi 启用 Aero Glass 的工作代码: 此功能已在 Windows7 64 位系统上进行了测试,可与 Delphi 2007、2010 和 Xe2(32 位和 64 位)一起使用。 我在网上找到的所有各种版本的 Delphi 函数都被破坏了——还有很多人抱怨访问冲突错误。 最终揭示修复错误代码的是 Gerry Coll 对AccessViolationException in Delphi - impossible (check it, unbelievable...) 的回复,该回复是关于尝试修复同一类型函数中的 AV 错误。

    function  ISAeroEnabled: Boolean;
    type
      _DwmIsCompositionEnabledFunc = function(var IsEnabled: Bool): HRESULT; stdcall;
    var
      Flag                       : BOOL;
      DllHandle                  : THandle;
      OsVersion                  : TOSVersionInfo;
      DwmIsCompositionEnabledFunc: _DwmIsCompositionEnabledFunc;
    begin
      Result:=False;
      ZeroMemory(@OsVersion, SizeOf(OsVersion));
      OsVersion.dwOSVersionInfoSize := SizeOf(TOSVERSIONINFO);
    
      if ((GetVersionEx(OsVersion)) and (OsVersion.dwPlatformId = VER_PLATFORM_WIN32_NT) and
          (OsVersion.dwMajorVersion = 6) and (OsVersion.dwMinorVersion < 2)) then //Vista&Win7 only (no Win8)
      begin
        DllHandle := LoadLibrary('dwmapi.dll');
        try
          if DllHandle <> 0 then
          begin
            @DwmIsCompositionEnabledFunc := GetProcAddress(DllHandle, 'DwmIsCompositionEnabled');
            if (@DwmIsCompositionEnabledFunc <> nil) then
            begin
              if DwmIsCompositionEnabledFunc(Flag)= S_OK then
               Result:= Flag;
            end;
          end;
        finally
          FreeLibrary(DllHandle);
        end;
      end;
    end;
    

    【讨论】:

    • 应该是OsVersion.dwMajorVersion = 6。从TOSVersion.MajorTOSVersion.Minor 也必须更容易阅读。更何况你写的函数是没必要的。使用Dwmapi.DwmCompositionEnabled
    • 您的函数在尝试排除 Windows 8 的方式上也有些奇怪。我不明白。基本上我认为这不能回答你提出的问题,而且这是一段非常具有误导性的代码。
    • 它有意排除 Windows 8,因为只有 Vista 和 Windows 7 支持 Aero Glass。
    • >>应该是 OsVersion.dwMajorVersion = 6。
    • 至于你回答中的函数,为什么不调用Dwmapi内置的函数呢?
    猜你喜欢
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 2011-10-02
    • 2021-06-22
    • 2023-01-03
    • 2014-06-07
    • 1970-01-01
    相关资源
    最近更新 更多