如何使用Delphi 2010以编程方式确定Windows的性能设置

时间:2012-12-17 10:59:28

标签: windows delphi winapi delphi-2010

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

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应用程序时,淡入淡出就差不多了 瞬间(最多可能是1/4秒,如果我眨眼,我会错过 转换)。

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

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

我在Delphi 2010和DelphiXE2上测试了这一点,结果是一样的。 这在Windows 7 Ultimate 64bit上进行了测试,如果这有任何区别的话。

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

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

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

至于解决方案...... 有没有办法判断Windows是否在垃圾图形/最高性能模式下运行,以便我可以在我的应用程序中禁用Alpha淡入淡出效果?


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

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


感谢任何帮助。

2 个答案:

答案 0 :(得分:7)

您的代码的根本问题在于,无论计算机的性能特征如何,您都在强制进行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秒。您可以随时调整数学,以根据您的要求修改持续时间。即使在低性能机器上,此代码也会产生平滑的淡入淡出。

我还要评论您不应在drmMain方法中使用全局变量TfrmMainTfrmMain方法已经可以访问该实例。它是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

了解如何执行此操作

答案 1 :(得分:0)

对于迟到的跟进感到抱歉,我花了一段时间才弄清楚我的问题及其背后的一些问题。

首先,感谢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显卡的系统上 - 小于.001秒   如果Aero Glass打开,如果Aero Glass关闭,大约需要3.7秒。现在   授予我的测试样本很小,3个NVidia系统(算上我的   最初报告该问题的客户)和一个非NVidia系统   但如果我使用的是体面的NVidia显卡我就不会打扰了   关闭航空玻璃。

以下是检测Aero Glass是否通过Delphi启用的工作代码: 此功能已在Windows7 64位系统上进行了测试,可与Delphi 2007,2010和Xe2(32&amp; 64bit)配合使用。 以下我在网上找到的所有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;