如何以编程方式确定 Windows 的性能设置 与德尔福 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应用程序时,渐变几乎是瞬间(最多可能¼秒,如果我眨眼,我就会错过过渡)

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

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

我在Delphi 2010和DelphiXE2上测试了这一点,结果是相同的。这是在Windows7Ultimate64位上测试过的,如果有什么不同的话。

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

  • 我认为forms Alpha属性由GPU处理,因此不会受到Windows性能设置的影响,而Windows性能设置应该以最大限度地提高CPU性能为目标

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

就修复而言。。。有没有办法判断Windows是否在垃圾图形/最高性能模式下运行,这样我就可以在应用程序中禁用Alpha渐变效果?


为清晰起见进行编辑:虽然我想修复褪色,但我真正想要的是确定Windows性能设置的方法。

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


感谢您的帮助。

代码的根本问题是,无论机器的性能特征如何,都会强制进行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版本的。就我个人而言,当最小化和最大化设置时,我会将行为建立在动画窗口的基础上。我的理由是,若用户不希望最小化和最大化被动画化,那个么他们可能不希望窗口关闭被淡化。

以下是如何读取该设置:

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读取。您应该能够通过遵循文档来找出如何做到这一点。

很抱歉跟进太晚了,但我花了一段时间才找到问题的有效答案及其背后的一些问题。

首先,感谢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性能选项设置是"启用桌面合成"one_answers">在Windows和按钮上使用视觉样式"。如果两个选项都启用了,则没有问题,如果其中一个设置未启用,则循环爬网**(如果表单最大化,则在我的系统上大约12秒)。

事实证明,打开或关闭Aero Glass会影响这两个设置。因此,能够检测Aero Glass是否打开,使我能够确定是否在我的应用程序中启用形式效果,如过渡渐变和其他养眼效果。此外,现在我还可以在错误报告中捕获这些信息。

**请注意,这似乎是NVidia问题/错误,或者至少是在使用NVidia显卡的系统上更严重的问题。在2不同的NVidia系统(如果不是最新的驱动程序,也是最新的)I对于混合形式的渐变,得到了类似的结果-小于如果Aero Glass打开,则为.001秒,如果Aero格拉斯打开,则约为12秒off.在使用英特尔显卡的系统上-不到.001秒如果Aero Glass打开,如果Aero格拉斯关闭,大约3.7秒。现在假设我的测试采样很小,3个NVidia系统(算上我的最初报告问题的客户)和一个非NVidia系统但如果我使用的是一个不错的NVidia显卡,我就不会麻烦了关闭Aero Glass。

以下是检测Aero Glass是否通过Delphi启用的工作代码:该功能已在Windows7 64位系统上进行了测试,并可与Delphi 2007、2010和Xe2(32&64位)配合使用。我在网上发现的所有不同版本的Delphi函数都被破坏了,还有一些人抱怨访问违规错误。Gerry Coll对Delphi中的AccessViolationException-impossible(检查一下,难以置信…)的回应最终揭示了修复坏代码的方法,这是关于试图修复同类型函数中的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;

最新更新