制作屏幕截图会导致计算机速度减慢(此时卡住)



请检查此代码:

procedure ScreenShotBMP(DestBitmap : TBitmap; AActiveWindow: Boolean = True) ;
var
  DC: HDC;
begin
  if AActiveWindow then
    DC := GetDC(GetForegroundWindow)
  else
    DC := GetDC(GetDesktopWindow);
  try
    DestBitmap.Width := GetDeviceCaps(DC, HORZRES);
    DestBitmap.Height := GetDeviceCaps(DC, VERTRES);
    BitBlt(DestBitmap.Canvas.Handle, 0, 0, DestBitmap.Width, DestBitmap.Height, DC, 0, 0, SRCCOPY);
  finally
    if AActiveWindow then
      ReleaseDC(GetForegroundWindow, DC)
    else
      ReleaseDC(GetDesktopWindow, DC);
  end;
end;

它可以正确地生成桌面或活动屏幕的屏幕截图,但在操作过程中电脑卡住了一点。

我需要应用程序在正常的时间范围内(不到1秒)进行屏幕截图,但运行这个程序会减慢计算机的速度。

它不消耗CPU,任务管理器没有显示任何异常活动,简单的整个系统都被卡住了。不管我是在主线程还是其他线程中运行此代码。

有没有其他方法可以创建不会减慢机器速度的屏幕截图?

谢谢。

基于XE5 VCL Win32应用程序的快速测试,我无法重现您的问题,该应用程序在Win7 64位、1280x1024分辨率、英特尔酷睿i7 860@2.80GHz(根据CPU-Z)、4GB DDR3 RAM上运行,使用以下测试代码:

function CaptureWindow(const WindowHandle: HWnd): TBitmap;
var
  DC: HDC;
  wRect: TRect;
  Width, Height: Integer;
begin
  DC := GetWindowDC(WindowHandle);
  Result := TBitmap.Create;
  try
    GetWindowRect(WindowHandle, wRect);
    Width := wRect.Right - wRect.Left;
    Height := wRect.Bottom - wRect.Top;
    Result.Width := Width;
    Result.Height := Height;
    Result.Modified := True;
    BitBlt(Result.Canvas.Handle, 0, 0, Width, Height, DC, 0, 0, SRCCOPY);
  finally
    ReleaseDC(WindowHandle, DC);
  end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
  Bmp: TBitmap;
  SW: TStopwatch;
  W, H: Integer;
begin
  SW := TStopwatch.StartNew;
  Bmp := CaptureWindow(GetDesktopWindow);
  try
    Image1.Picture.Assign(Bmp);
    W := Bmp.Width;
    H := Bmp.Height;
  finally
    Bmp.Free;
  end;
  SW.Stop;
  Self.Caption := Format('W: %d H: %d %d:%d %d',
                         [W,
                          H,
                          SW.Elapsed.Minutes, 
                          SW.Elapsed.Seconds,
                          SW.Elapsed.Milliseconds]);
end;

标题显示:W: 1280 H: 1024 0:0 42,这是一个42毫秒的运行时间,用于创建位图、捕获屏幕和BitBlt、将其分配给TImage进行显示和释放位图(更不用说对秒表代码中的高分辨率计时器的两次调用和运行时间的计算)。

注意:CaptureWindow代码是根据不久前有人在这里发布的内容改编的。它的Aero感知部分似乎没有必要,因为测试表明,无论在Windows 7上启用还是不启用Aero,它都能正常工作。(我猜这是Vista最初需要的东西。)

1)DestBitmap的PixelFormat属性有哪个值?对于快速BitBlt,源和目标的颜色格式必须相同。在您的情况下,PixelFormat必须具有pfDevice值。

2) 在GetForegroundWindow的情况下,为什么使用GetDeviceCaps而不是GetWindowRect?您使用较大的维度->BitBlt尝试复制更多的字节->BitBlt工作速度较慢。

3) 前景窗口可以在GetForegroundWindow和ReleaseDC之间更改(GetForegroundWindow,DC)->最好将窗口句柄保留在单独的变量中。

最新更新