0

我想在TBitmap对象上绘制整个表单,包括其标题栏和框架。

GetFormImage很酷,但它有两个问题:

  • 它也不绘制窗框。
  • 当表单被隐藏时它不起作用。

您有解决这些问题的想法吗?

4

3 回答 3

5

访问非客户区的关键是GetWindowDC功能,其他一切都照常进行

procedure TForm5.FormClick(Sender: TObject);
var
  Bitmap: TBitmap;
  DC: HDC;
  FileName: string;
begin
  Bitmap := TBitmap.Create;
  try
    Assert(HandleAllocated);
    DC := GetWindowDC(Handle);
    Win32Check(DC <> 0);

    Bitmap.SetSize(Width, Height);

    Win32Check(BitBlt(Bitmap.Canvas.Handle, 0, 0, Width, Height, DC, 0, 0, SRCCOPY));

    FileName := Name + '.' + GraphicExtension(TBitmap);
    Bitmap.SaveToFile(FileName);

    ShellExecute(HWND_DESKTOP, nil, PChar(FileName), nil, nil, SW_NORMAL);
  finally
    ReleaseDC(Handle, DC);
    Bitmap.Free;
  end;
end;

对于隐藏(未绘制!)窗口的第二种情况 - 请参阅 RRUZ 的评论。

于 2013-05-22T20:39:33.103 回答
1

关于隐藏时捕获表单图像,使用

AlphaBlend := true;
AlphaBlendValue := 0;

显示形式时。用户将看不到表单,但 GetFormImage() 将捕获其画布。我认为这也可以与“OnTheFly”建议一起使用。

于 2014-04-21T08:53:06.043 回答
1

这是我使用过的一个小功能,您可能会觉得很有用。

编辑:哎呀,我没有完全阅读这个问题。这可能不适用于隐藏窗口,但我不确定除非表单可以绘制框架本身,否则任何事情都不会,但操作系统不会。

function GetScreenShot(const aWndHandle:THandle; AeroAware:boolean=true):TBitmap;
var
  wWindow: HDC;
  wRect : TRect;
  wDesktop : THandle;
begin
  Result  := TBitmap.Create;
  try
    if AeroAware then
      wDesktop := GetDesktopWindow
    else
      wDesktop := aWndHandle;

    wWindow := GetDC(wDesktop);
    try
      Result.PixelFormat := pf32bit;
      GetWindowRect(aWndHandle, wRect);
      Result.Width := wRect.Right-wRect.Left;
      Result.Height := wRect.Bottom-wRect.Top;
      if AeroAware then
        BitBlt(Result.Canvas.Handle, 0, 0, Result.Width, Result.Height, wWindow, wRect.Left, wRect.Top, SRCCOPY)
      else
        BitBlt(Result.Canvas.Handle, 0, 0, Result.Width, Result.Height, wWindow, 0, 0, SRCCOPY);
      Result.Modified := True;
    finally
      ReleaseDC(wDesktop, wWindow);
    end;
  except
    Result.Free;
    Result := nil;
  end;
end;
于 2013-05-22T20:42:28.157 回答