首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TEdgeBrowser for Delphi -捕获选项卡内容并转发它

TEdgeBrowser for Delphi -捕获选项卡内容并转发它
EN

Stack Overflow用户
提问于 2022-06-28 18:50:19
回答 1查看 151关注 0票数 0

我正在浏览器/查看器Delphi应用程序中使用TEdgeBrowser组件。对于最初的实现,经过简短的学习曲线之后,我几乎没有什么问题。

现在,我可以尝试一些特性(比如屏幕截图)。

要将屏幕捕获到文件中,只需添加:

代码语言:javascript
复制
EdgeBrowser1.CapturePreview(ScrFileName);

其中ScrFileName是文件的路径,即c:\pic\screenshot.png

我希望每秒钟都能捕捉屏幕(并使用Indy组件(TIdHTTPServer)在内部中继屏幕(http)。

我可以这样做,但效率很低。有人能推荐另一种选择吗?

代码语言:javascript
复制
procedure TMainForm.IdHTTPServer1CommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
Const
  EOL = #13;
var
  Strm: TMemoryStream;
begin
  if ARequestInfo.Document = '' then
  begin
    AResponseInfo.Redirect('/');
  end
  else if ARequestInfo.Document = '/' then
  begin
    AResponseInfo.ResponseNo := 200;
    AResponseInfo.ContentType := 'text/html';
    AResponseInfo.ContentText := '<!DOCTYPE html>'+EOL+
      '<html>'+EOL+
      '<head>'+EOL+
      '<meta name="viewport" content="width=device-width, initial-scale=5">'+EOL+
      '<meta http-equiv="Refresh" content=1>'+EOL+
      '<style type="text/css">'+EOL+
      '  img.fullscr {'+EOL+
      '    display:block;'+EOL+
      '    width:100%;'+EOL+
      '  }'+EOL+
      '</style>'+EOL+
      '</head>'+EOL+
      '<body>'+EOL+
      '<img src="/image" class="fullscr">'+EOL+
      '</body>'+EOL+
      '</html>'+EOL;
  end
  else if ARequestInfo.Document = '/image' then
  begin
    Strm := TMemoryStream.Create;
    try
      Strm.Clear;
      Strm.LoadFromFile(ScrFileName);
      Strm.Position := 0;
      AResponseInfo.ResponseNo := 200;
      AResponseInfo.ContentType := 'image/png';
      AResponseInfo.ContentStream := Strm;
    except
      Strm.Free;
      raise;
    end;
  end
  else begin
    AResponseInfo.ResponseNo := 404;
  end;
end;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-28 19:44:06

您考虑过根本不将捕获的映像保存到磁盘上吗?TEdgeBrowser.CapturePreview()有一个重载,可以保存到TStream。您可以定期将捕获保存到与TMemoryStream共享的TIdHTTPServer,以便将最新捕获发送到HTTP客户端。

TIdHTTPServer是一个多线程组件,它的OnCommand...事件是在工作线程的上下文中触发的,所以一定要使用线程安全锁(如TCriticalSection )来保护TMemoryStream

例如:

代码语言:javascript
复制
private
  // using 2 TMemoryStreams so Edge can be preparing a new capture
  // while TIdHTTPServer continues serving the previous capture to
  // clients until the new capture is ready...
  CapturingImageStream: TMemoryStream;
  ReadyImageStream: TMemoryStream;
  ImageLock: TCriticalSection;

  // TODO: keep track of last capture time and etag, in case clients
  // want to use Conditional-GET requests ('If-Modified-Since' and
  // 'If-None-Match' HTTP headers) to cache retrievals in case captures
  // haven't changed yet in between multiple GET requests...

...

procedure TMainForm.FormCreate(Sender: TObject);
begin
  CapturingImageStream := TMemoryStream.Create;
  ReadyImageStream := TMemoryStream.Create;
  ImageLock := TCriticalSection.Create;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  IdHTTPServer1.Active := False;
  CapturingImageStream.Free;
  ReadyImageStream.Free;
  ImageLock.Free;
end;

procedure TMainForm.Timer1Timer(Sender: TObject);
var
  Strm: TMemoryStream;
begin
  CapturingImageStream.Clear;
  EdgeBrowser1.CapturePreview(CapturingImageStream);
  ImageLock.Enter;
  try
    Strm := ReadyImageStream;
    ReadyImageStream := CapturingImageStream;
    CapturingImageStream := Strm;
  finally
    ImageLock.Leave;
  end;
end;

procedure TMainForm.IdHTTPServer1CommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
  if ARequestInfo.Document = '' then
  begin
    AResponseInfo.Redirect('/');
  end
  else if ARequestInfo.Document = '/' then
  begin
    AResponseInfo.ResponseNo := 200;
    AResponseInfo.ContentType := 'text/html';
    AResponseInfo.ContentText := '<!DOCTYPE html>'+sLineBreak+
      '<html>'+sLineBreak+
      '<head>'+sLineBreak+
      '<meta name="viewport" content="width=device-width, initial-scale=5">'+sLineBreak+
      '<meta http-equiv="Refresh" content=1>'+sLineBreak+
      '<style type="text/css">'+sLineBreak+
      '  img.fullscr {'+sLineBreak+
      '    display:block;'+sLineBreak+
      '    width:100%;'+sLineBreak+
      '  }'+sLineBreak+
      '</style>'+sLineBreak+
      '</head>'+sLineBreak+
      '<body>'+sLineBreak+
      '<img src="/image" class="fullscr">'+sLineBreak+
      '</body>'+sLineBreak+
      '</html>'+sLineBreak;
  end
  else if ARequestInfo.Document = '/image' then
  begin
    ImageLock.Enter;
    try
      // TODO: check request's 'If-Modified-Since' and 'If-None-Match'
      // headers, send 304 if the current capture hasn't changed yet...

      ReadyImageStream.Position := 0;
      AResponseInfo.ResponseNo := 200;
      AResponseInfo.ContentType := 'image/png';
      AResponseInfo.ContentStream := ReadyImageStream;
      AResponseInfo.FreeContentStream := False;
      // need to send the ContentStream inside the read lock...
      AResponseInfo.WriteHeader;
      AResponseInfo.WriteContent;
    finally
      ImageLock.Leave;
    end;
  end
  else begin
    AResponseInfo.ResponseNo := 404;
  end;
end;

为了进一步优化这一点,您可以考虑更改HTML以使用客户端AJAX或WebSocket脚本定期请求和显示最新的图像,而不必每次重新加载整个HTML页面。

例如,如果您要使用WebSocket,您可以在代码中添加一个WebSocket服务器(Indy此时没有一个,但有第三方实现),并让WebSocket服务器在准备就绪时将一个新捕获推送到浏览器,而不必等待一个HTTP请求首先到达。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72791757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档